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

thread.c

Go to the documentation of this file.
00001 /*!
00002  * @file thread.c
00003  *
00004  * @brief Create and manage real machine Java thread structures.
00005  *
00006  *
00007  *
00008  * @section Control
00009  *
00010  * \$URL: https://svn.apache.org/path/name/thread.c $ \$Id: thread.c 0 09/28/2005 dlydick $
00011  *
00012  * Copyright 2005 The Apache Software Foundation
00013  * or its licensors, as applicable.
00014  *
00015  * Licensed under the Apache License, Version 2.0 ("the License");
00016  * you may not use this file except in compliance with the License.
00017  * You may obtain a copy of the License at
00018  *
00019  *     http://www.apache.org/licenses/LICENSE-2.0
00020  *
00021  * Unless required by applicable law or agreed to in writing,
00022  * software distributed under the License is distributed on an
00023  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
00024  * either express or implied.
00025  *
00026  * See the License for the specific language governing permissions
00027  * and limitations under the License.
00028  *
00029  * @version \$LastChangedRevision: 0 $
00030  *
00031  * @date \$LastChangedDate: 09/28/2005 $
00032  *
00033  * @author \$LastChangedBy: dlydick $
00034  *         Original code contributed by Daniel Lydick on 09/28/2005.
00035  *
00036  * @section Reference
00037  *
00038  */
00039 
00040 #include "arch.h"
00041 ARCH_COPYRIGHT_APACHE(thread, c, "$URL: https://svn.apache.org/path/name/thread.c $ $Id: thread.c 0 09/28/2005 dlydick $");
00042 
00043 
00044  
00045 #include <strings.h>
00046 
00047 #include "jvmcfg.h"
00048 #include "cfmacros.h"
00049 #include "classfile.h"
00050 #include "exit.h" 
00051 #include "gc.h" 
00052 #include "jvm.h"
00053 #include "jvmclass.h"
00054 #include "linkage.h" 
00055 #include "method.h" 
00056 #include "util.h"
00057 #include "utf.h"
00058 
00059 
00060 /*!
00061  * @brief Initialize the thread area of the JVM model.
00062  *
00063  *
00064  * @b Parameters: @link #rvoid rvoid@endlink
00065  *
00066  *
00067  *       @returns @link #rvoid rvoid@endlink
00068  *
00069  */
00070 rvoid thread_init()
00071 {
00072     for (CURRENT_THREAD = jvm_thread_index_null;
00073          CURRENT_THREAD < JVMCFG_MAX_THREADS;
00074          CURRENT_THREAD++)
00075     {
00076         jvm_thread_index thridx = CURRENT_THREAD;
00077 
00078         /********** Init thread state ******************/
00079 
00080         THREAD(thridx).id = thridx;
00081 
00082         THREAD(thridx).name = HEAP_GET_DATA(THREAD_NAME_MAX_LEN,rfalse);
00083         sprintfLocal(THREAD(thridx).name, "thread %d", thridx);
00084 
00085         THREAD(thridx).thread_objhash = jvm_object_hash_null;
00086 
00087         THREAD(thridx).priority   = THREAD_PRIORITY_MIN;
00088 
00089         THREAD(thridx).status     = THREAD_STATUS_EMPTY;
00090 
00091         THREAD(thridx).prev_state = THREAD_STATE_DEAD;
00092         THREAD(thridx).this_state = THREAD_STATE_DEAD;
00093         THREAD(thridx).next_state = THREAD_STATE_DEAD;
00094 
00095         THREAD(thridx).jointarget = jvm_thread_index_null;
00096         THREAD(thridx).sleeptime  = 0;
00097         THREAD(thridx).locktarget = jvm_object_hash_null;
00098 
00099 
00100         /********** Init thread's code facilities ******/
00101 
00102         PUT_PC_IMMEDIATE(thridx,
00103                          jvm_class_index_null,
00104                          jvm_method_index_bad,
00105                          jvm_attribute_index_bad,
00106                          jvm_attribute_index_bad,
00107                          jvm_pc_offset_bad);
00108 
00109         THREAD(thridx).pass_instruction_count = 0;
00110         THREAD(thridx).thread_instruction_count = 0;
00111 
00112         THREAD(thridx).stack          = (jint *) rnull;
00113         THREAD(thridx).sp             = JVMCFG_NULL_SP;
00114         THREAD(thridx).fp             = JVMCFG_NULL_SP;
00115         THREAD(thridx).fp_end_program = JVMCFG_NULL_SP;
00116 
00117     } /* For CURRENT_THREAD */
00118 
00119     /*! @todo  What should the priority be on these threads? */
00120     /*
00121      * Forcibly allocate jvmcfg_thread_index_null thread,
00122      * system thread, and GC thread.  (These threads are
00123      * @e never deallocated.)
00124      */
00125     THREAD(jvm_thread_index_null).priority = THREAD_PRIORITY_MAX;
00126     THREAD(jvm_thread_index_null).status = THREAD_STATUS_INUSE |
00127                                            THREAD_STATUS_NULL;
00128     THREAD(jvm_thread_index_null).this_state = THREAD_STATE_NEW;
00129     THREAD(jvm_thread_index_null).next_state = THREAD_STATE_NEW;
00130 
00131     THREAD(JVMCFG_SYSTEM_THREAD).priority = THREAD_PRIORITY_MIN;
00132     THREAD(JVMCFG_SYSTEM_THREAD).status =   THREAD_STATUS_EMPTY;
00133 
00134     THREAD(JVMCFG_GC_THREAD).priority = THREAD_PRIORITY_MAX;
00135     THREAD(JVMCFG_GC_THREAD).status = THREAD_STATUS_INUSE;
00136     THREAD(JVMCFG_GC_THREAD).this_state = THREAD_STATE_NEW;
00137     THREAD(JVMCFG_GC_THREAD).next_state = THREAD_STATE_NEW;
00138 
00139 
00140     /* Last thread allocated */
00141     pjvm->thread_new_last = JVMCFG_GC_THREAD;
00142 
00143     /* First thread to run */
00144     CURRENT_THREAD = JVMCFG_SYSTEM_THREAD;
00145 
00146     /* Declare this module initialized */
00147     jvm_thread_initialized = rtrue;
00148 
00149     return;
00150 
00151 } /* END of thread_init() */
00152 
00153 
00154 /*!
00155  * @brief Look up table for names of thread states.
00156  *
00157  */
00158 const rchar *thread_state_names[THREAD_STATE_MAX_STATE + 1 + 1] =
00159 {
00160     THREAD_STATE_NEW_DESC,
00161     THREAD_STATE_START_DESC,
00162     THREAD_STATE_RUNNABLE_DESC,
00163     THREAD_STATE_RUNNING_DESC,
00164     THREAD_STATE_COMPLETE_DESC,
00165     THREAD_STATE_BLOCKINGEVENT_DESC,
00166     THREAD_STATE_BLOCKED_DESC,
00167     THREAD_STATE_UNBLOCKED_DESC,
00168     THREAD_STATE_SYNCHRONIZED_DESC,
00169     THREAD_STATE_RELEASE_DESC,
00170     THREAD_STATE_WAIT_DESC,
00171     THREAD_STATE_NOTIFY_DESC,
00172     THREAD_STATE_LOCK_DESC,
00173     THREAD_STATE_ACQUIRE_DESC,
00174     THREAD_STATE_DEAD_DESC,
00175     THREAD_STATE_BADLOGIC_DESC,
00176 
00177     /* For out of bounds indices, both <0 and >max */
00178     THREAD_STATE_ILLEGAL_DESC
00179 };
00180 
00181 /*!
00182  * @brief Map state numbers to state names.
00183  *
00184  *
00185  * @param  state   state number per @b THREAD_STATE_xxx definitions
00186  *
00187  * @returns string name of that state
00188  *
00189  */
00190 const rchar *thread_state_get_name(rushort state)
00191 {
00192 
00193 /* Unsigned type makes this unnecessary **
00194     if (THREAD_STATE_MIN_STATE > state)
00195     {
00196         ** illegal state number **
00197         return(thread_state_names[THREAD_STATE_MAX_STATE + 1]);
00198     }
00199 */
00200 
00201     if (THREAD_STATE_MAX_STATE < state)
00202     {
00203         /* illegal state number */
00204         return(thread_state_names[THREAD_STATE_MAX_STATE + 1]);
00205     }
00206 
00207     return(thread_state_names[state]);
00208 
00209 } /* END of thread_state_get_name() */
00210 
00211 
00212 /*!
00213  * @brief Locate an unused thread table slot for a new thread.
00214  *
00215  *
00216  * @b Parameters: @link #rvoid rvoid@endlink
00217  *
00218  *
00219  * @returns Thread table index of an empty slot.
00220  *          Throw error if no slots.
00221  *
00222  *
00223  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00224  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00225  *         if no thread slots are available@endlink.
00226  *
00227  */
00228 static jvm_thread_index thread_allocate_slot(rvoid)
00229 {
00230     jvm_thread_index thridx =
00231         (JVMCFG_MAX_THREADS == (1 + pjvm->thread_new_last))
00232         ? 1 + pjvm->thread_new_last
00233         : JVMCFG_FIRST_THREAD;
00234 
00235     /* Count allocated slots in case all slots are full */
00236     jvm_thread_index count  = 0;
00237 
00238     while(rtrue)
00239     {
00240         if (THREAD(thridx).status & THREAD_STATUS_INUSE)
00241         {
00242             /* Point to next slot, wrap around at end */
00243             thridx++;
00244 
00245             if (thridx == JVMCFG_MAX_THREADS)
00246             {
00247                 thridx = JVMCFG_FIRST_THREAD;
00248             }
00249 
00250             /* Limit high value to end of table */
00251             if (pjvm->thread_new_last == JVMCFG_MAX_THREADS - 1)
00252             {
00253                 pjvm->thread_new_last = JVMCFG_FIRST_THREAD;
00254             }
00255 
00256 
00257             /* Count this attempt and keep looking */
00258             count++;
00259 
00260             if (count == (JVMCFG_MAX_THREADS - JVMCFG_FIRST_THREAD))
00261             {
00262                 /* No more slots, cannot continue */
00263                 exit_throw_exception(EXIT_JVM_THREAD,
00264                                    JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR);
00265 /*NOTREACHED*/
00266             }
00267 
00268             /* Keep looking */
00269             continue;
00270         }
00271 
00272         /*
00273          * Declare slot in use, but not initialized.
00274          */
00275         THREAD(thridx).status =
00276                                THREAD_STATUS_INUSE | THREAD_STATUS_NULL;
00277 
00278 
00279         /* This slot is empty, report it for allocation */
00280 
00281         pjvm->thread_new_last = thridx;
00282 
00283         return(thridx);
00284     }
00285 /*NOTREACHED*/
00286     return(jvm_thread_index_null); /* Satisfy compiler */
00287 
00288 } /* END of thread_allocate_slot() */
00289 
00290 
00291 /*!
00292  * @name Thread allocation and loading.
00293  *
00294  * @brief Allocate a new thread from the thread area and load a class
00295  * to run on it.
00296  *
00297  * Activity on the system thread @link #JVMCFG_SYSTEM_THREAD
00298    JVMCFG_SYSTEM_THREAD@endlink will @e not attempt to load a
00299  * @c @b java.lang.Thread to represent a thread as an object.
00300  * This is because the system thread is for internal use only outside
00301  * the normal JVM runtime environment.
00302  *
00303  * As a variation, allocate the system thread
00304  * (@link #JVMCFG_SYSTEM_THREAD JVMCFG_SYSTEM_THREAD@endlink)
00305  * for an internal task.  This method-- thread_new_common()-- is the
00306  * common routine, where thread_new() is the general-purpose function
00307  * and thread_new_system() is for loading a class onto the system
00308  * thread.
00309  *
00310  * @warning Do @e not attempt to call this function
00311  *          with @b codeatridx set to @link #jvm_attribute_index_native
00312             jvm_attribute_index_native@endlink because this code
00313  *          does not apply to native methods.  Call that native
00314  *          method directly from the code instead!
00315  *
00316  * @param  thridx        Thread index of unused thread-- for
00317  *                         thread_new_common() only-- the others
00318  *                         generate this value and pass it in.
00319  *
00320  * @param  clsidx        Class index of code to run
00321  *
00322  * @param  mthidx        Method index of code to run
00323  *
00324  * @param  codeatridx    Method's attribute index of code to run
00325  *
00326  * @param  excpatridx    Method's attribute index of exception index tbl
00327  *
00328  * @param  priority      @link #THREAD_PRIORITY_NORM
00329                          THREAD_PRIORITY_xxx@endlink value for
00330  *                       thread priority
00331  *
00332  * @param  isdaemon      Daemon thread, @link #rtrue rtrue@endlink or
00333  *                       @link #rfalse rfalse@endlink
00334  *
00335  *
00336  * @returns index to thread slot containing this thread.
00337  *
00338  *
00339  * @throws JVMCLASS_JAVA_LANG_STACKOVERFLOWERROR
00340  *         @link #JVMCLASS_JAVA_LANG_STACKOVERFLOWERROR
00341  *         if loading the class on this thread would overfill
00342  *         the JVM stack for this thread.@endlink.
00343  *         for this thread.
00344  *
00345  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00346  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00347  *         if no class slots or thread slots are available.@endlink.
00348  *
00349  *
00350  */
00351 
00352 /*@{ */ /* Begin grouped definitions */
00353 
00354 /*!
00355  * @brief Common function to load a class on a thread to be run.
00356  *
00357  * Given a thread index, load a method onto it to be run.
00358  * <em>Do not</em> use this function to load a method onto
00359  * a thread that has existing JVM execution active because
00360  * the stack is initialized and the method entry point loaded
00361  * into the PC.  See @link #opcode_run() opcode_run()@endlink
00362  * for examples of how to accomplish this in other ways.
00363  *
00364  */
00365 static jvm_thread_index thread_new_common(jvm_thread_index    thridx,
00366                                           jvm_class_index     clsidx,
00367                                           jvm_method_index    mthidx,
00368                                          jvm_attribute_index codeatridx,
00369                                          jvm_attribute_index excpatridx,
00370                                           rint                priority,
00371                                           rboolean            isdaemon)
00372 {
00373     /*
00374      * Declare slot in use, but not initialized.
00375      * (Redundant for most situations where
00376      * thread_allocate_slot() was called, but needed
00377      * for initializing classes like JVMCFG_NULL_THREAD
00378      * or JVMCFG_SYSTEM_THREAD with an absolute slot
00379      * number that was not searched for by the allocator.)
00380      */
00381     THREAD(thridx).status = THREAD_STATUS_INUSE | THREAD_STATUS_NULL;
00382 
00383     /* Check for stack overflow if this frame is loaded */
00384     ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx)->pcfs;
00385     Code_attribute *pca = (Code_attribute *)
00386                          &pcfs->methods[mthidx]->attributes[codeatridx];
00387 
00388     /* Check if this causes stack overflow, throw StackOverflowError */
00389     if (JVMCFG_MAX_SP <= GET_SP(thridx) +
00390                          JVMREG_STACK_MIN_FRAME_HEIGHT +
00391                          JVMREG_STACK_PC_HEIGHT +
00392                          pca->max_stack +
00393                          pca->max_locals)
00394     {
00395         exit_throw_exception(EXIT_THREAD_STACK,
00396                              JVMCLASS_JAVA_LANG_STACKOVERFLOWERROR);
00397 /*NOTREACHED*/
00398     }
00399 
00400     /*!
00401      * If no stack overflow would occur during execution,
00402      * continue to load up a new thread.  Unless this class
00403      * will run on the system thread, start out by generating
00404      * a new @c @b java.lang.Thread object to represent
00405      * this thread in the object table.
00406      *
00407      * @todo  Need to also implement java.lang.ThreadGroup as a
00408      *        preparatory step to instantiating java.lang.Thread
00409      */
00410     if (JVMCFG_SYSTEM_THREAD == thridx)
00411     {
00412         THREAD(thridx).thread_objhash = jvm_object_hash_null;
00413     }
00414     else
00415     {
00416         jvm_class_index clsidxTHR =
00417             class_find_by_prchar(JVMCLASS_JAVA_LANG_THREAD);
00418 
00419         if (jvm_class_index_null == clsidxTHR)
00420         {
00421             /* unreserve thread and quit */
00422             THREAD(thridx).status = THREAD_STATUS_EMPTY;
00423 
00424             /* No more slots, cannot continue */
00425             exit_throw_exception(EXIT_JVM_THREAD,
00426                                  JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR);
00427 /*NOTREACHED*/
00428         }
00429 
00430         jvm_table_linkage *ptl = CLASS_OBJECT_LINKAGE(clsidxTHR);
00431 
00432         jvm_object_hash objhashTHR =
00433             object_instance_new(OBJECT_STATUS_EMPTY,
00434                                 ptl->pcfs,
00435                                 ptl->clsidx,
00436                                 LOCAL_CONSTANT_NO_ARRAY_DIMS,
00437                                 (jint *) rnull,
00438                                 rtrue,
00439                                 thridx);
00440 
00441         THREAD(thridx).thread_objhash = objhashTHR;
00442         (rvoid) GC_OBJECT_MKREF_FROM_OBJECT(jvm_object_hash_null,
00443                                          THREAD(thridx).thread_objhash);
00444     }
00445 
00446     /*
00447      * Only allocate stack to an allocated thread
00448      * (not in thread_init()), and thereafter keep
00449      * that allocation until thread_die().
00450      */
00451     if (rnull == THREAD(thridx).stack)
00452     {
00453         THREAD(thridx).stack =
00454             (jint *) HEAP_GET_STACK(JVMCFG_STACK_SIZE, rfalse);
00455     }
00456 
00457     /*
00458      * First two word of stack are reserved
00459      */
00460     PUT_SP_IMMEDIATE(thridx, JVMCFG_NULL_SP);
00461 
00462     /*
00463      * First 1 word meaningless in and of itself, but
00464      * when setting up the frame pointer for the first frame,
00465      * the fact that it is zero will mean that the inner
00466      * @c @b while() loop will not exit until a
00467      * @c @b return is done from the very last frame. 
00468      */
00469     PUT_SP_WORD(thridx, GET_SP(thridx), CLASSFILE_MAGIC);
00470 
00471     /*
00472      * FINAL fp MUST be @e zero (null SP) so CHECK_FINAL_STACK_FRAME()
00473      * works, if used.
00474      */
00475     PUT_FP_IMMEDIATE(thridx, GET_SP(thridx));
00476 
00477     /* with jvm_class_index_null class index, other fields meaningless*/
00478     PUT_PC_IMMEDIATE(thridx,
00479                      jvm_class_index_null,
00480                      jvm_method_index_bad,
00481                      jvm_attribute_index_bad,
00482                      jvm_attribute_index_bad,
00483                      jvm_pc_offset_bad);
00484 
00485     /*
00486      * Reserve first full stack frame, 1st amount of locals,
00487      * null FP, null PC.
00488      *
00489      * @note  jvmutil_print_stack_common() requires FP to hold a
00490      *        value of @link #JVMCFG_NULL_SP JVMCFG_NULL_SP@endlink
00491      *        as its terminating condition.  So also should @e any
00492      *        logic that scans the stack.  See in particular the
00493      *        @link #FIRST_STACK_FRAME() FIRST_STACK_FRAME()@endlink and
00494      *        @link #NEXT_STACK_FRAME() NEXT_STACK_FRAME()@endlink and
00495      *        @link #CHECK_FINAL_STACK_FRAME
00496               CHECK_FINAL_STACK_FRAME()@endlink macros.
00497      */
00498     PUSH_FRAME(thridx, pca->max_locals);
00499 
00500     /*
00501      * Stack frame now can accept operand stacking, including
00502      * requests for PUSH_FRAME(), which is used when calling
00503      * a JVM method or other subroutine.
00504      *
00505      * Upon final POP_FRAME(), the FP and PC will both be
00506      * empty, @link #JVMCFG_NULL_SP JVMCFG_NULL_SP@endlink and
00507      * @link #jvm_class_index_null jvm_class_index_null@endlink,
00508      * respectively.  At this point, the JVM thread
00509      * should stop running since there is nothing else
00510      * to do.
00511      *
00512      * Allocation complete, set priority and ISDAEMON status (as
00513      * requrested), and move next thread state to @b NEW, then
00514      * report to caller.
00515      */
00516     THREAD(thridx).priority = priority;
00517     threadstate_request_new(thridx);
00518     threadstate_activate_new(thridx);
00519 
00520     /*!
00521      * @todo Any time the isdaemon field is modified, MAKE SURE
00522      *       that the value in the @c @b java.lang.Thread
00523      *       instance variable is set to the same value.  This
00524      *       should @e never be an issue except when instantiating
00525      *       a new @c @b java.lang.Thread object since the
00526      *       API docs say that it can only be set @e once.
00527      */
00528     if (rtrue == isdaemon)
00529     {
00530         THREAD(thridx).status |= THREAD_STATUS_ISDAEMON;
00531     }
00532 
00533     /* Thread slot completely initialized */
00534     THREAD(thridx).status &= ~THREAD_STATUS_NULL;
00535 
00536     /* Load JVM program counter for first instruction */
00537     PUT_PC_IMMEDIATE(thridx,
00538                      clsidx,
00539                      mthidx,
00540                      codeatridx,
00541                      excpatridx,
00542                      CODE_CONSTRAINT_START_PC);
00543 
00544     return(thridx);
00545 
00546 } /* END of thread_new_common() */
00547 
00548 
00549 /*!
00550  * @brief Reserve the system thread and load a class to run on it.
00551  *
00552  * Reserve the system thread specifically-- see description
00553  * above for thread_new_common()
00554  *
00555  */
00556 static jvm_thread_index thread_new_system(jvm_class_index     clsidx,
00557                                           jvm_method_index    mthidx,
00558                                          jvm_attribute_index codeatridx,
00559                                          jvm_attribute_index excpatridx,
00560                                           rint                priority,
00561                                           rboolean            isdaemon)
00562 {
00563     /* Check if system thread is already in use */
00564     if (THREAD(JVMCFG_SYSTEM_THREAD).status & THREAD_STATUS_INUSE)
00565     {
00566         /* Somebody goofed */
00567         exit_throw_exception(EXIT_JVM_INTERNAL,
00568                              JVMCLASS_JAVA_LANG_INTERNALERROR);
00569 /*NOTREACHED*/
00570     }
00571 
00572     /* If not already in use, reserve it and perform thread setup */
00573     return(thread_new_common(JVMCFG_SYSTEM_THREAD,
00574                              clsidx,
00575                              mthidx,
00576                              codeatridx,
00577                              excpatridx,
00578                              priority,
00579                              isdaemon));
00580 
00581 } /* END of thread_new_system() */
00582 
00583 
00584 /*!
00585  * @brief Allocate a new thread from the thread area and
00586  * load a class to run on it.
00587  *
00588  * General-purpuse version-- see description above for
00589  * thread_new_common()
00590  *
00591  */
00592 static jvm_thread_index thread_new(jvm_class_index      clsidx,
00593                                    jvm_method_index     mthidx,
00594                                    jvm_attribute_index  codeatridx,
00595                                    jvm_attribute_index  excpatridx,
00596                                    rint                 priority,
00597                                    rboolean             isdaemon)
00598 {
00599     jvm_thread_index thridx = thread_allocate_slot();
00600 
00601     /* Set up thread resources and finish */
00602     return(thread_new_common(thridx,
00603                              clsidx,
00604                              mthidx,
00605                              codeatridx,
00606                              excpatridx,
00607                              priority,
00608                              isdaemon));
00609 
00610 } /* END of thread_new() */
00611 
00612 /*@} */ /* End of grouped definitions */
00613 
00614 
00615 
00616 /*!
00617  * @brief Load a class onto a thread during JVM initialization.
00618  *
00619  * Allocate a new thread and load a class (array or non-array),
00620  * prepare to invoke @c @b static methods, and prepare
00621  * to start thread.
00622  *
00623  * Classes loaded through this function will not be marked as
00624  * referenced, but will also not be marked for garbage collection,
00625  * either.
00626  *
00627  *
00628  * @param  clsname           Name of class to load.
00629  *
00630  * @param  mthname           Name of method in class.
00631  *
00632  * @param  mthdesc           Description of method parameters and
00633  *                           return type.
00634  *
00635  * @param  priority          THREAD_PRIORITY_xxx value for thread
00636  *                           priority.
00637  *
00638  * @param  isdaemon          Daemon thread, @link #rtrue rtrue@endlink
00639  *                           or @link #rfalse rfalse@endlink
00640  *
00641  * @param  usesystemthread   Allocate the system thread with
00642  *                           thread_new_system() instead of
00643  *                           a user thread via thread_new_system(),
00644  *                           @link #rtrue rtrue@endlink
00645  *                           or @link #rfalse rfalse@endlink.
00646  *
00647  * @param find_registerNatives When @link #rtrue rtrue@endlink,
00648  *                           will return the ordinal for
00649  *                           @link #JVMCFG_JLOBJECT_NMO_REGISTER 
00650                              JVMCFG_JLOBJECT_NMO_REGISTER@endlink and
00651  *                           @link #JVMCFG_JLOBJECT_NMO_UNREGISTER 
00652                              JVMCFG_JLOBJECT_NMO_UNREGISTER@endlink
00653  *                           as well as the other ordinals.  Once JVM
00654  *                           initialization is complete, this should
00655  *                           always be @link #rfalse rfalse@endlink
00656  *                           because all future classes should @e never
00657  *                           have local ordinals.
00658  *
00659  *
00660  * @returns Thread index of NEW thread, ready to move to START state,
00661  *          or throw error if no slots.
00662  *
00663  *
00664  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00665  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00666  *         if no class slots or thread slots are available.@endlink.
00667  *
00668  * @throws JVMCLASS_JAVA_LANG_CLASSNOTFOUNDEXCEPTION
00669  *         @link #JVMCLASS_JAVA_LANG_CLASSNOTFOUNDEXCEPTION
00670  *         if class cannot be located.@endlink.
00671  *
00672  * @throws JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR
00673  *         @link #JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR
00674  *         if the requested method is not found in the class
00675  *         or has no code area.@endlink.
00676  *
00677  * @throws JVMCLASS_JAVA_LANG_STACKOVERFLOWERROR
00678  *         @link #JVMCLASS_JAVA_LANG_STACKOVERFLOWERROR
00679  *         if loading the class on this thread would overfill
00680  *         the JVM stack for this thread.@endlink.
00681  *
00682  */
00683 jvm_thread_index thread_class_load(rchar            *clsname,
00684                                    rchar            *mthname,
00685                                    rchar            *mthdesc,
00686                                    rint              priority,
00687                                    rboolean          isdaemon,
00688                                    rboolean          usesystemthread,
00689                                    rboolean        find_registerNatives)
00690 {
00691     /*
00692      * Attempt to load requested class.  Notice that
00693      * an object is @e not being instantiated here,
00694      * so the @b arraylength parm (parm 3) can be
00695      * @link #rnull rnull@endlink.
00696      */
00697     jvm_class_index clsidx = class_load_from_prchar(clsname,
00698                                                    find_registerNatives,
00699                                                     (jint *) rnull);
00700 
00701     /* Point to @e this class structure, then get immediate superclass*/
00702     ClassFile *pcfs         = CLASS_OBJECT_LINKAGE(clsidx)->pcfs;
00703     ClassFile *pcfs_recurse = pcfs;
00704 
00705     /*
00706      * Make special exception for @c @b java.lang.Object,
00707      * no superclass
00708      */
00709     if (CONSTANT_CP_DEFAULT_INDEX == pcfs_recurse->super_class)
00710     {
00711         pcfs_recurse = (ClassFile *) rnull;
00712     }
00713     else
00714     {
00715         pcfs_recurse =
00716             CLASS_OBJECT_LINKAGE(
00717                 class_find_by_prchar(
00718                     PTR_CP1_CLASS_NAME_STRNAME(pcfs_recurse,
00719                                             pcfs_recurse->super_class)))
00720             ->pcfs;
00721     }
00722 
00723     /* Iterate through class table looking for superclasses */
00724     while(rnull != pcfs_recurse)
00725     {
00726         /* case (1), check if class is actually an interface */
00727         if (ACC_INTERFACE & pcfs_recurse->access_flags)
00728         {
00729             exit_throw_exception(EXIT_JVM_CLASS,
00730                        JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR);
00731 /*NOTREACHED*/
00732         }
00733 
00734         /*
00735          * Take care of special case where
00736          * @link robject#super_class super_class@link is zero, namely
00737          * represents @c @b java.lang.Object, the only class
00738          * without a direct superclass.  This condition @e must be
00739          * the end of the scan.  If this condition is never met,
00740          * the possibility of a class circularity error is probably
00741          * almost 100%.
00742          */
00743         if (CONSTANT_CP_DEFAULT_INDEX == pcfs_recurse->super_class)
00744         {
00745             break;
00746         }
00747 
00748         /* case (2), check if class eventually references itself */
00749         if (0 == utf_prchar_classname_strcmp(
00750                      clsname,
00751                      pcfs_recurse,
00752                      pcfs_recurse->super_class))
00753         {
00754             /*
00755              * Don't permit recursive call to error handler
00756              * (this one should @e never happen)
00757              */
00758             if (0 == strcmp(clsname,
00759                             JVMCLASS_JAVA_LANG_CLASSCIRCULARITYERROR))
00760             {
00761                 exit_throw_exception(EXIT_JVM_CLASS,
00762                               JVMCLASS_JAVA_LANG_CLASSCIRCULARITYERROR);
00763 /*NOTREACHED*/
00764             }
00765         }
00766 
00767         /* Go get next higher superclass and scan again */
00768         pcfs_recurse =
00769             CLASS_OBJECT_LINKAGE(
00770                 class_find_by_prchar(
00771                     PTR_CP1_CLASS_NAME_STRNAME(pcfs_recurse,
00772                                         pcfs_recurse->super_class)))
00773             ->pcfs;
00774 
00775     } /* while pcfs_recurse */
00776 
00777     /*
00778      * Locate starting PC in this class for this method with
00779      * this descriptor by scanning method[] table.
00780      * Since this function is @e never called from the JVM runtime,
00781      * the use of (rchar *) strings for mthname and mthdesc is
00782      * acceptable.  Normal usage would call method_find() directly
00783      * using pointers to UTF8 constant_pool entries.
00784      */
00785 
00786     jvm_method_index mthidx = method_find_by_prchar(clsidx,
00787                                                     mthname,
00788                                                     mthdesc);
00789 
00790     /* Failed to locate method name, throw ClassNotFoundException */
00791     if (jvm_method_index_bad == mthidx)
00792     {
00793         exit_throw_exception(EXIT_JVM_CLASS,
00794                              JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR);
00795 /* NOTREACHED*/
00796     }
00797 
00798     /* Since method name and description match, go run thread */
00799     jvm_attribute_index codeatridx =
00800         pcfs->methods[mthidx]->LOCAL_method_binding.codeatridxJVM;
00801 
00802     /* Load exception index table also, if present */
00803     jvm_attribute_index excpatridx =
00804         pcfs->methods[mthidx]->LOCAL_method_binding.excpatridxJVM;
00805 
00806     /* Load native method ordinal number, if applicable */
00807  /* jvm_native_method_ordinal nmord =
00808         pcfs->methods[mthidx]->LOCAL_method_binding.nmordJVM; */
00809 
00810     /* Typically will not happen-- if have valid method,also have code*/
00811     if (jvm_attribute_index_bad == codeatridx)
00812     {
00813         exit_throw_exception(EXIT_JVM_ATTRIBUTE,
00814                              JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR);
00815 /* NOTREACHED*/
00816     }
00817 
00818     /* Do not permit this operation for a native method request */
00819     if (jvm_attribute_index_native == codeatridx)
00820     {
00821         exit_throw_exception(EXIT_JVM_INTERNAL,
00822                              JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR);
00823 /*NOTREACHED*/
00824     }
00825  
00826     /*
00827      * Everything was found.  Now allocate thread to run this
00828      * static method of this class.
00829      */
00830     if (rtrue == usesystemthread)
00831     {
00832         return(thread_new_system(clsidx,
00833                                  mthidx,
00834                                  codeatridx,
00835                                  excpatridx,
00836                                  priority,
00837                                  isdaemon));
00838     }
00839     else
00840     {
00841         return(thread_new(clsidx,
00842                           mthidx,
00843                           codeatridx,
00844                           excpatridx,
00845                           priority,
00846                           isdaemon));
00847     }
00848 
00849 } /* END of thread_class_load() */
00850 
00851 
00852 /*!
00853  * @brief Terminate and deallocate a thread that is currently in
00854  * the @b DEAD state.
00855  *
00856  *
00857  * @param thridx thread index of thread to be deallocated.
00858  *
00859  * @returns @link #rtrue rtrue@endlink if successful,
00860  *          else @link #rfalse rfalse@endlink.
00861  *
00862  */
00863 
00864 rboolean thread_die(jvm_thread_index thridx)
00865 {
00866     if (THREAD_STATE_DEAD == THREAD(thridx).this_state)
00867     {
00868         /*!
00869          * Mark ONLY fields requiring it, leave rest alone for
00870          * post-mortem use by developer.
00871          *
00872          * @todo  Could leave stack in place for post-mortem if
00873          *        it is assumed that there would be a reasonable
00874          *        amount of contents still valid in memory.
00875          */
00876         HEAP_FREE_STACK(THREAD(thridx).stack);
00877         THREAD(thridx).stack = (jint *) rnull;
00878 
00879         THREAD(thridx).status &= ~THREAD_STATUS_INUSE;
00880 
00881         return(rtrue);
00882     }
00883 
00884     return(rfalse);
00885 
00886 } /* END of thread_die() */
00887 
00888 
00889 /*!
00890  * @brief Shut down the thread area of the JVM model
00891  * at the end of JVM execution.
00892  *
00893  *
00894  * @b Parameters: @link #rvoid rvoid@endlink
00895  *
00896  *
00897  *       @returns @link #rvoid rvoid@endlink
00898  *
00899  */
00900 rvoid thread_shutdown()
00901 {
00902     jvm_thread_index thridx;
00903 
00904     for (thridx = jvm_thread_index_null;
00905          thridx < JVMCFG_MAX_THREADS;
00906          thridx++)
00907     {
00908         if (THREAD_STATUS_INUSE & THREAD(thridx).status)
00909         {
00910             /*
00911              * check stack frames only if stack area present
00912              */
00913             if (rnull != THREAD(thridx).stack)
00914             {
00915                 /* Locate first (top) stack frame's FP */
00916                 jvm_sp fp = FIRST_STACK_FRAME(thridx);
00917 
00918                 /*
00919                  * First frame is @e greater than 0, and @e contains
00920                  * the NULL frame pointer.
00921                  */
00922                 if (JVMCFG_NULL_SP == fp)
00923                 {
00924                     continue;
00925                 }
00926 
00927                 /*
00928                  * Pop all stack frames, free local storage,
00929                  * clear object references, etc. (via POP_FRAME() macro)
00930                  */
00931                 while(!CHECK_FINAL_STACK_FRAME_GENERIC(thridx, fp))
00932                 {
00933                     /*
00934                      * Get next FP @e before popping that storage
00935                      * location off of the stack!
00936                      */
00937                     fp = NEXT_STACK_FRAME_GENERIC(thridx, fp);
00938 
00939                     POP_FRAME(thridx);
00940                 }
00941 
00942                 /*
00943                  * The current implementation does some of these steps
00944                  * internally, but be thorough so it does not break when
00945                  * the implementation changes.
00946                  */
00947                 threadstate_request_badlogic(thridx);
00948                 threadstate_activate_badlogic(thridx);
00949                 threadstate_process_badlogic(thridx);
00950                 threadstate_request_complete(thridx);
00951                 threadstate_activate_complete(thridx);
00952                 threadstate_process_complete(thridx);
00953                 threadstate_request_dead(thridx);
00954                 threadstate_activate_dead(thridx);
00955                 threadstate_process_dead(thridx);
00956             }
00957         }
00958 
00959         /*
00960          * Keep thread name around usually
00961          * (not wiped out in thread_die() function)
00962          */
00963         if (rnull != THREAD(thridx).name)
00964         {
00965             HEAP_FREE_STACK(THREAD(thridx).name);
00966             /* THREAD(thridx).name = (rchar *) rnull; */
00967         }
00968     }
00969 
00970     /* This may result in a @e large garbage collection */
00971     GC_RUN(rfalse);
00972 
00973     /* Declare this module uninitialized */
00974     jvm_thread_initialized = rfalse;
00975 
00976     return;
00977 
00978 } /* END of thread_shutdown() */
00979 
00980 
00981 /*!
00982  * @brief Set up JVM thread-relative exception handler-- implements
00983  * @c @b setjmp(3)/longjmp(3).
00984  *
00985  *
00986  * @param thridx  Thread table index of thread for which to set up
00987  *                this exception handler.
00988  *
00989  *
00990  * @returns From normal setup, integer @link
00991             #THREAD_STATUS_EMPTY THREAD_STATUS_EMPTY@endlink.
00992  *          Otherwise, return error code passed in to
00993  *          @link #thread_throw_exception()
00994                    thread_throw_exception()@endlink as shown below.
00995  *
00996  *
00997  * @internal
00998  * @c @b setjmp(3) and @c @b struct[idx].member do _not_ get
00999  * along at all:
01000  *
01001  * @verbatim
01002       
01003        int nonlocal_rc =
01004                     setjmp(*THREAD(thridx).nonlocal_ThrowableEvent);
01005       
01006    @endverbatim
01007  *
01008  * To get this working, the @link rthread#pnonlocal_ThrowableEvent
01009  * nonlocal_ThrowableEvent@endlink had to be changed to a pointer
01010  * and a buffer allocated from heap.  This probably is due to the
01011  * @c @b typedef syntax of @c @b jmp_buf and a
01012  * long array, which pointers like.  However, instead of playing
01013  * games with addressing &element[0], a pointer works better because
01014  * not all @c @b jmp_buf implementations wil be a long array.
01015  *
01016  */
01017 
01018 int thread_exception_setup(jvm_thread_index thridx)
01019 {
01020     THREAD(thridx).pnonlocal_ThrowableEvent =
01021                                  HEAP_GET_DATA(sizeof(jmp_buf), rfalse);
01022 
01023     return(setjmp(*THREAD(thridx).pnonlocal_ThrowableEvent));
01024 
01025 } /* END of thread_exception_setup() */
01026  
01027 
01028 /*!
01029  * @brief Global handler setup for JVM thread errors and
01030  * exceptions-- implements @c @b setjmp(3).
01031  *
01032  *
01033  * @param thridx Thread index of thread where exception occurred.
01034  *
01035  * @param thread_status_bits Type of exception being generated,
01036  *          typically using one of the following exit codes from
01037  *          the status bits in
01038  *          @link jvm/src/thread.h thread.h@endlink
01039  *          per the definition there of each code:
01040  *
01041  * <ul><li> @link #THREAD_STATUS_THREW_EXCEPTION
01042                    THREAD_STATUS_THREW_EXCEPTION@endlink
01043  * </li>
01044  * <li>     @link #THREAD_STATUS_THREW_ERROR
01045                    THREAD_STATUS_THREW_ERROR@endlink
01046  * </li>
01047  * <li>     @link #THREAD_STATUS_THREW_THROWABLE
01048                    THREAD_STATUS_THREW_THROWABLE@endlink
01049  * </li>
01050  * <li>     @link #THREAD_STATUS_THREW_UNCAUGHT
01051                    THREAD_STATUS_THREW_UNCAUGHT@endlink
01052  * </li></ul>
01053  *
01054  * @param exception_name Null-terminated string name of error or
01055  *                       exception class to be invoked as a result
01056  *                       of this situation.
01057  *
01058  *
01059  * @returns non-local state restoration from setup via @c @b setjmp(3)
01060  *          as stored in @link
01061             #exit_LinkageError exit_LinkageError@endlink
01062  *          buffer by @link #exit_init() exit_init()@endlink
01063  *          in @link #jvm_init() jvm_init()@endlink before any of
01064  *          these errors could occur. All code invoking this
01065  *          function should use the standard @c @b lint(1) comment for
01066  *          "code not reached" as shown after the @c @b longjmp(3)
01067  *          function call in the source code of this function:
01068  *          <b>/</b><b>*NOTREACHED*</b><b>/</b>
01069  *
01070  */
01071 rvoid thread_throw_exception(jvm_thread_index  thridx,
01072                              rushort           thread_status_bits,
01073                              rchar            *exception_name)
01074 {
01075     /* Disallow invalid status from being reported */
01076     switch (thread_status_bits)
01077     {
01078         case THREAD_STATUS_THREW_EXCEPTION:
01079         case THREAD_STATUS_THREW_ERROR:
01080         case THREAD_STATUS_THREW_THROWABLE:
01081         case THREAD_STATUS_THREW_UNCAUGHT:
01082             break;
01083         default:
01084             exit_throw_exception(EXIT_JVM_INTERNAL,
01085                                  JVMCLASS_JAVA_LANG_INTERNALERROR);
01086 /*NOTREACHED*/
01087     }
01088 
01089     THREAD(thridx).status |= thread_status_bits;
01090 
01091     THREAD(thridx).pThrowableEvent = exception_name;
01092 
01093 
01094     int rc = (int) thread_status_bits;
01095 
01096     longjmp(*THREAD(thridx).pnonlocal_ThrowableEvent, rc);
01097 /*NOTREACHED*/
01098 
01099 } /* END of thread_throw_exception() */
01100 
01101 
01102 /* EOF */
01103 

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