Thread: [Sablevm-developer] java.lang.Thread.yield()
Brought to you by:
egagnon
From: Chris P. <chr...@ma...> - 2003-02-20 01:36:52
|
Hi Etienne, For 1.0.6, you might want to replace sched_yield() with if (sched_yield() != 0) _svmf_error_InternalError (env); in java_lang_Thread.c I don't know what JNI_OK is defined to be (I couldn't find it with grep), but if it's zero then that's: if (sched_yield() != JNI_OK) _svmf_error_InternalError (env); Now my multithreaded programs run sometimes (they still segfault randomly). Chris P.S. David and I were wondering if you were going to make a development branch of SableVM that it's safe to hack away on (probably saves you the pain of having to apply all these patches). |
From: Prof. E. M. G. <eti...@uq...> - 2003-02-20 02:18:57
|
On Wed, Feb 19, 2003 at 08:36:58PM -0500, Chris Pickett wrote: > I don't know what JNI_OK is defined to be (I couldn't find it with > grep), but if it's zero then that's: > > if (sched_yield() != JNI_OK) > _svmf_error_InternalError (env); No!!!! JNI_OK is used by _svmf_* functions to indicate success. You should never make any relation between the actual integer value JNI_OK is defined as, and the accidental value it matches in another context! If I decided to change JNI_OK to be defined as 36, the code above would start misbehaving (assuming JNI_OK was originally defined as zero). Also, you should *ALWAYS* check return values of non-void functions. I had not double-checked if sched_yield returned a value. I guess I should never trust submitted code and review thoroughly every line of code and the documentation of every called library function... This means I should probably double-check whether sched_yield is actually a POSIX compliant function? (No GNU specific code allowed; SableVM makes portability claims). Etienne -- Etienne M. Gagnon, Ph.D. http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Chris P. <chr...@ma...> - 2003-02-20 02:35:44
|
Hi Etienne, Prof. Etienne M. Gagnon wrote: >On Wed, Feb 19, 2003 at 08:36:58PM -0500, Chris Pickett wrote: > > >>I don't know what JNI_OK is defined to be (I couldn't find it with >>grep), but if it's zero then that's: >> >>if (sched_yield() != JNI_OK) >> _svmf_error_InternalError (env); >> >> > >No!!!! JNI_OK is used by _svmf_* functions to indicate success. You >should never make any relation between the actual integer value JNI_OK >is defined as, and the accidental value it matches in another context! > > >If I decided to change JNI_OK to be defined as 36, the code above >would start misbehaving (assuming JNI_OK was originally defined as >zero). > Okay. Where is JNI_OK defined? > >Also, you should *ALWAYS* check return values of non-void functions. >I had not double-checked if sched_yield returned a value. I guess I >should never trust submitted code and review thoroughly every line of >code and the documentation of every called library function... > > Well, actually, I realized last night about checking the error status, after I emailed you to say that I would send a patch today, but then today you had already committed the code. Then I got caught up in making scripts, and didn't get around to telling you yet. sched_yield() returns 0 if there was no problem, or -1 if there was an error. sched_yield() is not necessarily posix compliant, so perhaps you'd better use pthread_yield() ... pthread_yield() doesn't return a value ever either, so just replace sched_yield() with pthread_yield() and forget about the error check. sched_yield() is in sched.h which is in the GNU C library, whereas pthread_yield() is in pthreads. The only reason I used sched_yield() was because that's what you and Clark and I talked about. Sorry for not letting you know earlier and not checking the code I sent you. Transgression #1. Chris |
From: Prof. E. M. G. <eti...@uq...> - 2003-02-20 03:01:17
|
On Wed, Feb 19, 2003 at 09:35:54PM -0500, Chris Pickett wrote: > Okay. Where is JNI_OK defined? My first question would be: why do you need this information? > Well, actually, I realized last night about checking the error status,=20 > after I emailed you to say that I would send a patch today, but then=20 > today you had already committed the code. Then I got caught up in=20 > making scripts, and didn't get around to telling you yet. >=20 > sched_yield() returns 0 if there was no problem, or -1 if there was an=20 > error. >=20 > sched_yield() is not necessarily posix compliant, so perhaps you'd=20 > better use pthread_yield() ... pthread_yield() doesn't return a value=20 > ever either, so just replace sched_yield() with pthread_yield() and=20 > forget about the error check. My documentation says: $ man sched_yield =2E.. CONFORMING TO POSIX.1b (formerly POSIX.4) =2E.. Also, aborting the VM if this call fails is quite dramatic! The VM should only be aborted if you have detected an error in the VM itself, or if something REALLY bad happened (e.g. memory corruption). Otherwize, you throw either an "expected" exception (if appropriate), or you throw Error otherwise, as specified in the Java+JVM specifications. OK. Next time you'll be more careful and ask questions if you are unsure. ;-) I encourage you to look at my fix to your code, once I check-it in CVS. Etienne --=20 Etienne M. Gagnon, Ph.D. http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Chris P. <chr...@ma...> - 2003-02-20 03:24:43
|
Prof. Etienne M. Gagnon wrote: >On Wed, Feb 19, 2003 at 09:35:54PM -0500, Chris Pickett wrote: > > >>Okay. Where is JNI_OK defined? >> >> > >My first question would be: why do you need this information? > > Well it's used all over the place in your code and I thought it would help me to understand it better. The reason I included it in that function was because there are many other uses of JNI_OK in java_lang_Thread.c. Bruno just answered my question, so it's probably a good idea if I look at jni.h a bit. > > >>Well, actually, I realized last night about checking the error status, >>after I emailed you to say that I would send a patch today, but then >>today you had already committed the code. Then I got caught up in >>making scripts, and didn't get around to telling you yet. >> >>sched_yield() returns 0 if there was no problem, or -1 if there was an >>error. >> >>sched_yield() is not necessarily posix compliant, so perhaps you'd >>better use pthread_yield() ... pthread_yield() doesn't return a value >>ever either, so just replace sched_yield() with pthread_yield() and >>forget about the error check. >> >> > > >My documentation says: > >$ man sched_yield >... >CONFORMING TO > POSIX.1b (formerly POSIX.4) >... > > Okay, sched.h conforms to POSIX.1b, but it's still the GNU C library, so if you don't want dependence on sched.h then use pthread_yield(). They do the same thing . . . > >Also, aborting the VM if this call fails is quite dramatic! The VM >should only be aborted if you have detected an error in the VM itself, >or if something REALLY bad happened (e.g. memory corruption). > Well, the sched_yield() documentation at http://www.gnu.org/manual/glibc-2.2.5/html_node/Basic-Scheduling-Functions.html says: int *sched_yield*/ (void) / Function This function voluntarily gives up the process' claim on the CPU. Technically, |sched_yield| causes the calling process to be made immediately ready to run (as opposed to running, which is what it was before). This means that if it has absolute priority higher than 0, it gets pushed onto the tail of the queue of processes that share its absolute priority and are ready to run, and it will run again when its turn next arrives. If its absolute priority is 0, it is more complicated, but still has the effect of yielding the CPU to other processes. If there are no other processes that share the calling process' absolute priority, this function doesn't have any effect. To the extent that the containing program is oblivious to what other processes in the system are doing and how fast it executes, this function appears as a no-op. The return value is |0| on success and in the pathological case that it fails, the return value is |-1| and |errno| is set accordingly. There is nothing specific that can go wrong with this function, so there are no specific |errno| values. ============== And so I figured it was a pretty bad thing if the yield() didn't work because it says pathological, so I thought killing the VM was reasonable. Again, I was just copying what you did elsewhere in the file. > >Otherwize, you throw either an "expected" exception (if appropriate), >or you throw Error otherwise, as specified in the Java+JVM >specifications. > >OK. Next time you'll be more careful and ask questions if you are >unsure. ;-) > >I encourage you to look at my fix to your code, once I check-it in >CVS. > I will. For now, you should probably check every line of code that I submit ... it's not so uncommon to have reviewers and even super-reviewers (for large projects). However, everything's under revision control anyway so no matter what happens to the source tree it will never be the end of the world. Cheers, Chris |
From: Prof. E. M. G. <eti...@uq...> - 2003-02-20 04:03:43
|
On Wed, Feb 19, 2003 at 10:24:44PM -0500, Chris Pickett wrote: > Well it's used all over the place in your code and I thought it would=20 > help me to understand it better. The reason I included it in that=20 > function was because there are many other uses of JNI_OK in=20 > java_lang_Thread.c. OK. > Bruno just answered my question, so it's probably a good idea if I look= =20 > at jni.h a bit. You should read the JNI specification book. It is very well written. It has a first part that explains how to use the JNI interface from a programmer's perspective (giving much insight on the reason why things are setup that way), and the second part is the specification itself. This is where JNI_OK is really defined. The JNI interface has had a very deep impact on the architecture of SableVM. This is why I think you should read the document (in addition to reading the JVM specification, of course). jni.h encodes what is specified in the JNI book. > Okay, sched.h conforms to POSIX.1b, but it's still the GNU C library, so= =20 > if you don't want dependence on sched.h then use pthread_yield(). They= =20 > do the same thing . . . The GNU C library (commonly called glibc or libc6) implements the standard C library + POSIX + other things + GNU extentions. You simply have to restrict yourself to using Standard C + POSIX compatible calls. =2E.. > And so I figured it was a pretty bad thing if the yield() didn't work=20 > because it says pathological, so I thought killing the VM was reasonable. If you look at my solution, you'll note that I suggest that we might simply ignore the return value anyway. This is why your original code semmed OK to me (I was assuming you had already investigated about return values & POSIX compliance). Have fun. Etienne --=20 Etienne M. Gagnon, Ph.D. http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Bruno D. <bru...@ma...> - 2003-02-20 03:10:31
|
Hi Chris, Etienne is right. You do not need to know where JNI_OK is defined. Unless you want to modify the value (and you don't want to that, of course), you should not care. But to satisfy your curiosity, look at src/libsablevm/include/jni.h. This is the standard place to define it, BTW. You should have been able to find that easily using grep. Cheers, Bruno On Thursday 20 February 2003 02:35 am, Chris Pickett wrote: > Hi Etienne, > > Prof. Etienne M. Gagnon wrote: > >On Wed, Feb 19, 2003 at 08:36:58PM -0500, Chris Pickett wrote: > >>I don't know what JNI_OK is defined to be (I couldn't find it with > >>grep), but if it's zero then that's: > >> > >>if (sched_yield() != JNI_OK) > >> _svmf_error_InternalError (env); > > > >No!!!! JNI_OK is used by _svmf_* functions to indicate success. You > >should never make any relation between the actual integer value JNI_OK > >is defined as, and the accidental value it matches in another context! > > > > > >If I decided to change JNI_OK to be defined as 36, the code above > >would start misbehaving (assuming JNI_OK was originally defined as > >zero). > > Okay. Where is JNI_OK defined? > > >Also, you should *ALWAYS* check return values of non-void functions. > >I had not double-checked if sched_yield returned a value. I guess I > >should never trust submitted code and review thoroughly every line of > >code and the documentation of every called library function... > > Well, actually, I realized last night about checking the error status, > after I emailed you to say that I would send a patch today, but then > today you had already committed the code. Then I got caught up in > making scripts, and didn't get around to telling you yet. > > sched_yield() returns 0 if there was no problem, or -1 if there was an > error. > > sched_yield() is not necessarily posix compliant, so perhaps you'd > better use pthread_yield() ... pthread_yield() doesn't return a value > ever either, so just replace sched_yield() with pthread_yield() and > forget about the error check. > > sched_yield() is in sched.h which is in the GNU C library, whereas > pthread_yield() is in pthreads. The only reason I used sched_yield() > was because that's what you and Clark and I talked about. > > Sorry for not letting you know earlier and not checking the code I sent > you. Transgression #1. > > Chris |
From: Chris P. <chr...@ma...> - 2003-02-20 04:23:22
|
> > >If you look at my solution, you'll note that I suggest that we might >simply ignore the return value anyway. This is why your original code >semmed OK to me (I was assuming you had already investigated about >return values & POSIX compliance). > > Okay, I looked at your solution, but apart from the goto end:, it doesn't seem different from the fix I suggested a couple of hours ago (ignoring the JNI_OK stuff): if (sched_yield() != 0) _svmf_error_InternalError (env); whereas you have: *if* (sched_yield () != 0) { //* Should we really really throw an error on failure? Maybe we could simply ignore the return value, if no harm is implied. Suggestions are welcome. Etienne *// _svmf_error_InternalError (env); *goto* *end*; } *end*: ................ is there really a big difference? or are you mainly talking about the comment? Cheers, Chris P.S. Can you get the JNI book online? I have the JVM spec as part of the Java docs, but I take it this is something else. |
From: Prof. E. M. G. <eti...@uq...> - 2003-02-20 05:07:21
|
On Wed, Feb 19, 2003 at 11:23:31PM -0500, Chris Pickett wrote: > Okay, I looked at your solution, but apart from the goto end:, it=20 > doesn't seem different from the fix I suggested a couple of hours ago=20 > (ignoring the JNI_OK stuff): >...=20 > is there really a big difference? or are you mainly talking about the=20 > comment? It seems I have read your code a little too quickly; I thought you were calling _svmf_abort(or fatal_error?) [this is why I was talking about aborting]. It's probably because it is late, and because without the goto end I assumed the call didn't return (which is what _svmm_fatal_error() does). The "goto end" is important for maintenance. Imagine somebody modifies the code: if (sched_yield() !=3D 0) _svmf_error_InternalError (env); yield_done =3D JNI_TRUE; =2E.. This would be wrong, whereas: if (sched_yield() !=3D 0) = = =20 { _svmf_error_InternalError (env); = = =20 goto end; } yield_done =3D JNI_TRUE; = = =20 end: =2E.. does the intended thing. > P.S. Can you get the JNI book online? I have the JVM spec as part of=20 > the Java docs, but I take it this is something else. Not really. Only the specification part is online (with a few errors, though), but the user guide part is not. Prof. Hendren should have a copy of it somewhere. Etienne --=20 Etienne M. Gagnon, Ph.D. http://www.info.uqam.ca/~egagnon/ SableVM: http://www.sablevm.org/ SableCC: http://www.sablecc.org/ |
From: Bruno D. <bru...@ma...> - 2003-02-20 05:26:25
|
On Thursday 20 February 2003 05:01 am, Prof. Etienne M. Gagnon wrote: > On Wed, Feb 19, 2003 at 11:23:31PM -0500, Chris Pickett wrote: > > Okay, I looked at your solution, but apart from the goto end:, it > > doesn't seem different from the fix I suggested a couple of hours ago > > (ignoring the JNI_OK stuff): > >... > > is there really a big difference? or are you mainly talking about the > > comment? > > It seems I have read your code a little too quickly; I thought you > were calling _svmf_abort(or fatal_error?) [this is why I was talking > about aborting]. It's probably because it is late, and because > without the goto end I assumed the call didn't return (which is what > _svmm_fatal_error() does). > > The "goto end" is important for maintenance. Imagine somebody > modifies the code: > > if (sched_yield() != 0) > _svmf_error_InternalError (env); > > yield_done = JNI_TRUE; > > ... > > > This would be wrong, whereas: > > if (sched_yield() != 0) > { > _svmf_error_InternalError (env); > goto end; > } > > yield_done = JNI_TRUE; > > end: > ... > > does the intended thing. > > > P.S. Can you get the JNI book online? I have the JVM spec as part of > > the Java docs, but I take it this is something else. > > Not really. Only the specification part is online (with a few errors, > though), but the user guide part is not. Prof. Hendren should have a > copy of it somewhere. Not quite true. Visit http://java.sun.com/docs/books/jni/index.html It seems like the entire book is there. (or http://java.sun.com/docs/books/index.html in general website for entire series) Bruno > > Etienne |