00001 /*! 00002 * @file objectutil.c 00003 * 00004 * @brief Utility and glue functions for 00005 * @link jvm/src/class.c class.c@endlink 00006 * and @c @b java.lang.Object 00007 * 00008 * Various functions in this file tend to get moved around between 00009 * @link jvm/src/threadutil.c threadutil.c@endlink and 00010 * @link jvm/src/threadutil.c classutil.c@endlink. 00011 * 00012 * 00013 * @internal Due to the fact that the implementation of the Java object 00014 * and the supporting robject structure is deeply embedded in the core 00015 * of the development of this software, this file has contents 00016 * that come and go during development. Some functions get 00017 * staged here before deciding where they @e really go; some 00018 * are interim functions for debugging, some were glue that eventually 00019 * went away. Be careful to remove prototypes to such functions 00020 * from the appropriate header file. 00021 * 00022 * 00023 * @section Control 00024 * 00025 * \$URL: https://svn.apache.org/path/name/objectutil.c $ \$Id: objectutil.c 0 09/28/2005 dlydick $ 00026 * 00027 * Copyright 2005 The Apache Software Foundation 00028 * or its licensors, as applicable. 00029 * 00030 * Licensed under the Apache License, Version 2.0 ("the License"); 00031 * you may not use this file except in compliance with the License. 00032 * You may obtain a copy of the License at 00033 * 00034 * http://www.apache.org/licenses/LICENSE-2.0 00035 * 00036 * Unless required by applicable law or agreed to in writing, 00037 * software distributed under the License is distributed on an 00038 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 00039 * either express or implied. 00040 * 00041 * See the License for the specific language governing permissions 00042 * and limitations under the License. 00043 * 00044 * @version \$LastChangedRevision: 0 $ 00045 * 00046 * @date \$LastChangedDate: 09/28/2005 $ 00047 * 00048 * @author \$LastChangedBy: dlydick $ 00049 * Original code contributed by Daniel Lydick on 09/28/2005. 00050 * 00051 * @section Reference 00052 * 00053 */ 00054 00055 #include "arch.h" 00056 ARCH_COPYRIGHT_APACHE(objectutil, c, "$URL: https://svn.apache.org/path/name/objectutil.c $ $Id: objectutil.c 0 09/28/2005 dlydick $"); 00057 00058 00059 #include "jvmcfg.h" 00060 #include "classfile.h" 00061 #include "jvm.h" 00062 #include "jvmclass.h" 00063 #include "linkage.h" 00064 00065 00066 /*! 00067 * @brief Attempt to @c @b synchronize() on an object's 00068 * monitor lock by contending for it. 00069 * 00070 * If acquired, stay in the @b RUNNING state. If not, go to the 00071 * @b SYNCHRONIZED state and arbitrate for it in the @b LOCK state. 00072 * 00073 * 00074 * @param objhashthis Object table hash of @c @b this object. 00075 * 00076 * @param thridx Thread table index of a thread requesting 00077 * ownership of this object's monitor lock. 00078 * 00079 * 00080 * @returns @link #rtrue rtrue@endlink if this thread now owns 00081 * this object's monitor lock, 00082 * otherwise @link #rfalse rfalse@endlink. 00083 * 00084 * 00085 * @todo Make sure @b IllegalMonitorStateException logic covers all 00086 * possibilities or needs to be removed. 00087 * 00088 * @todo Make sure thread interruption logic below here is working. 00089 * 00090 * @throws JVMCLASS_JAVA_LANG_NULLPOINTEREXCEPTION 00091 * @link #JVMCLASS_JAVA_LANG_NULLPOINTEREXCEPTION 00092 if the object hash is the null object@endlink, 00093 * typically due to bad input parameter. 00094 * 00095 * @throws JVMCLASS_JAVA_LANG_ILLEGALMONITORSTATEEXCEPTION 00096 * @link #JVMCLASS_JAVA_LANG_ILLEGALMONITORSTATEEXCEPTION 00097 if current thread cannot possibly own the object's monitor lock@endlink, 00098 * typically due to bad input parameter. 00099 * 00100 */ 00101 00102 rboolean objectutil_synchronize(jvm_object_hash objhashthis, 00103 jvm_thread_index thridx) 00104 { 00105 #if 0 00106 /* If this thread cannot possibly own the object's monitor lock */ 00107 if (some_condition) 00108 { 00109 thread_throw_exception(CURRENT_THREAD, 00110 THREAD_STATUS_THREW_EXCEPTION, 00111 JVMCLASS_JAVA_LANG_ILLEGALMONITORSTATEEXCEPTION); 00112 /*NOTREACHED*/ 00113 } 00114 #endif 00115 00116 /* Requested object must be in use and not null */ 00117 if ((OBJECT_STATUS_INUSE & OBJECT(objhashthis).status) && 00118 ((!(OBJECT_STATUS_NULL & OBJECT(objhashthis).status)))) 00119 { 00120 /* If nobody has it locked, */ 00121 if ((!((OBJECT_STATUS_MLOCK & OBJECT(objhashthis).status))) || 00122 00123 /* or if I already own it */ 00124 ((OBJECT_STATUS_MLOCK & OBJECT(objhashthis).status) && 00125 (OBJECT(objhashthis).mlock_thridx == CURRENT_THREAD))) 00126 { 00127 /* 00128 * Not currently locked, or currently own it anyway, 00129 * so take ownership. 00130 */ 00131 OBJECT(objhashthis).status |= OBJECT_STATUS_MLOCK; 00132 00133 OBJECT(objhashthis).mlock_count++; 00134 00135 OBJECT(objhashthis).mlock_thridx = CURRENT_THREAD; 00136 00137 /* No longer needed now that thread has ownership */ 00138 THREAD(thridx).locktarget = jvm_object_hash_null; 00139 00140 return(rtrue); 00141 } 00142 else 00143 { 00144 /* 00145 * If currently locked, tell thread model which object 00146 * is requested and go to @b SYNCHRONIZED to arbitrate 00147 * for the lock. 00148 */ 00149 THREAD(thridx).locktarget = objhashthis; 00150 00151 /* 00152 * This @e present function gets called later from 00153 * this @b SYNCHRONIZED @b REQUEST functino call, but 00154 * not until the state machine reaches the @b PROCESS 00155 * phase of the @b LOCK state (at a later time). This 00156 * means that either this same @c @b else block 00157 * will get invoked again during lock arbitration in 00158 * the @b LOCK state or the opposite @c @b if 00159 * block will be called to acquire the MLOCK. In both 00160 * cases, this present function will be invoked at 00161 * least once more before synchronization is complete. 00162 * 00163 */ 00164 (rvoid) threadstate_request_synchronized(thridx); 00165 00166 return(rfalse); 00167 } 00168 } 00169 00170 /* This thread cannot possibly own the object's monitor lock */ 00171 thread_throw_exception(CURRENT_THREAD, 00172 THREAD_STATUS_THREW_EXCEPTION, 00173 JVMCLASS_JAVA_LANG_NULLPOINTEREXCEPTION); 00174 /*NOTREACHED*/ 00175 return(rfalse); /* Satisfy compiler */ 00176 00177 } /* END of objectutil_synchronize() */ 00178 00179 00180 /*! 00181 * @brief Release @c @b synchronize from an object monitor lock. 00182 * 00183 * 00184 * @param objhashthis Object table hash of @c @b this object. 00185 * 00186 * @param thridx Thread table index of a thread requesting 00187 * to remove this object's monitor lock. 00188 * 00189 * 00190 * @attention Notice that the @link #rthread.locktarget 00191 locktarget@endlink is @b NOT cleared here! 00192 * This is so that the value may be retained 00193 * until the thread successfully arbitrates 00194 * for ownership again in threadstate_process_lock(). 00195 * Once the MLOCK is reacquired there, the 00196 * @link #rthread.locktarget locktarget@endlink will 00197 * have been cleared by objectutil_synchronize(). 00198 * The purpose of objectutil_release() is to provide 00199 * an avenue in the @b RUNNING state to release an MLOCK 00200 * and set up @link #rthread.locktarget locktarget@endlink 00201 * for the @b WAIT, @b NOTIFY, @b LOCK, @b ACQUIRE process. 00202 * 00203 * @returns @link #rvoid rvoid@endlink 00204 * 00205 * 00206 * @todo Make sure thread interruption logic below here is working. 00207 * 00208 * 00209 * @throws JVMCLASS_JAVA_LANG_ILLEGALMONITORSTATEEXCEPTION 00210 * @link #JVMCLASS_JAVA_LANG_ILLEGALMONITORSTATEEXCEPTION 00211 if current thread does not own the object's monitor lock@endlink. 00212 * 00213 */ 00214 rvoid objectutil_unsynchronize(jvm_object_hash objhashthis, 00215 jvm_thread_index thridx) 00216 { 00217 /* Requested object must be in use and not null */ 00218 if ((!(OBJECT_STATUS_INUSE & OBJECT(objhashthis).status)) || 00219 (OBJECT_STATUS_NULL & OBJECT(objhashthis).status)) 00220 { 00221 /*! @todo Should the not INUSE condition cause INTERNALERROR? */ 00222 00223 thread_throw_exception(CURRENT_THREAD, 00224 THREAD_STATUS_THREW_EXCEPTION, 00225 JVMCLASS_JAVA_LANG_NULLPOINTEREXCEPTION); 00226 /*NOTREACHED*/ 00227 } 00228 00229 /* This thread must own the monitor lock in order to unlock it */ 00230 if ((OBJECT_STATUS_MLOCK & OBJECT(objhashthis).status) && 00231 (thridx == (OBJECT(objhashthis).mlock_thridx))) 00232 { 00233 /* Decrement lock count and release MLOCK if done */ 00234 OBJECT(objhashthis).mlock_count--; 00235 00236 if (0 == OBJECT(objhashthis).mlock_count) 00237 { 00238 OBJECT(objhashthis).status &= ~OBJECT_STATUS_MLOCK; 00239 00240 OBJECT(objhashthis).mlock_thridx = jvm_thread_index_null; 00241 } 00242 return; 00243 } 00244 00245 /* This thread does not own the object's monitor lock */ 00246 thread_throw_exception(CURRENT_THREAD, 00247 THREAD_STATUS_THREW_EXCEPTION, 00248 JVMCLASS_JAVA_LANG_ILLEGALMONITORSTATEEXCEPTION); 00249 /*NOTREACHED*/ 00250 return; /* Satisfy compiler */ 00251 00252 } /* END of objectutil_unsynchronize() */ 00253 00254 00255 /*! 00256 * @brief Attempt to @c @b wait() on an object's 00257 * monitor lock by releasing it and requesting @b RELEASE state. 00258 * 00259 * Save the MLOCK to be released for subsequent 00260 * processing by threadstate_request_release(). 00261 * 00262 * 00263 * @param objhashthis Object table hash of @c @b this object. 00264 * 00265 * @param thridx Thread table index of a thread requesting 00266 * to release this object's monitor lock. 00267 * 00268 * @returns the result of threadstate_request_release() 00269 * 00270 */ 00271 rboolean objectutil_release(jvm_object_hash objhashthis, 00272 jvm_thread_index thridx) 00273 { 00274 /* Preserve MLOCK object's hash for transition to next states */ 00275 THREAD(thridx).locktarget = objhashthis; 00276 00277 return(threadstate_request_release(thridx)); 00278 00279 } /* END of objectutil_release() */ 00280 00281 00282 /* EOF */ 00283