Saturday, March 14. 2009, 08:44 PM
Until now we only used JamVM in single-threaded mode, because firstly, saving and restoring of Java-context has not been supported in the kernel, secondly, the kernel oopsed reproducibly but at various places when multiple jamvm threads were running. Finally I found time to study this problem, and have "recognized its nature." It turned out to be the same old problem with "rotated" registers. JEM implements Java Operand Stack in the first 8 general purpose registers, and pushes and pops them using some internal rotation. When such a rotation is in effect, access to single and to multiple registers actually hit different registers. For example, a "load multiple" (LDM) from registers r0-r7 returns values v0-v7, but reading r0 using MOV or another single-register instruction can actually deliver v1, or any other value, depending on the number of elements on Java Stack. This rotation is enabled always as long as the R bit in the Status Register is set. It has been known since early days of JEM development, that this bit does not get automatically cleared when leaving JEM mode. A thread that once has entered JEM has the R bit set for its entire life-time. Only when switching into the supervisor (kernel) mode or to a different thread the Status Register gets replaced and the R bit is cleared. This is the reason we have to wind and unwind the Java Operand Stack on every entry to and exit from the JEM mode. It now turned out, that also other threads in JamVM process get the R bit set! And not only once at their creation time. Clearing the R bit at fork time is not enough - it gets set again and again! Unfortunately, it is still absolutely unclear_how_ and where it gets set. A workaround has been implemented to clear the R bit upon every context switch, if the thread we are switching to is not going to run in JEM mode. This eliminated oopses for now and allows us to further work on multithreading support in JEM.