Ok, a bit more progress. There is still quite a few things to puzzle
out. I don't want to pound the VM with a ticker update every millisecond. I don't have a nice way to schedule a wakeup event sometime in the future by using some generic pthread service. I therefore re-implemented the logic that clock checks every message send and backward jump to check the current time and consider the next wakeup time. Likely we'll have to tune this, or perhaps 0.5% of run time devoted to looking at the clock is just good enough programming. Given all that I'm still dealing with having the second instance of the interpreter unlock the global vm logic so plugins can load in a clean manner. I did stick in a change where it does halt the 2nd instance when there is no squeak process runnable and no pending Delay but that isn't a correct solution. However I now am at the point where I can do HydraVM loadAndRunNewImage: 'test.image' HydraVM doIt: 'Transcript show: 10000 factorial' at: 2 Which then prints a really big number, later. I can of course interact with the main interpreter instance, and also do the 10000 factorial, which then makes my machine run at 200% cpu and whirl the fans to high. Going forward I need some folks who can compile the VM and do some testing. Also I still have to do a sanity check and review all the global & static variable usage in the mac specific code, and the drawing isn't correct, menu's get drawn with full transparency. -- = = = ======================================================================== John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ======================================================================== |
On May 8, 2008, at 12:30 AM, John M McIntosh wrote: Ok, a bit more progress. There is still quite a few things to puzzle out. I'll see it when I get your code. I therefore re-implemented the logic that clock checks every message send and backward jump to Or use it now, and return to it in a years time when our insight in this problem has improved. Unless it involves extensive coding. Amit Singh might have a good solution handy. I am looking through http://www.kernelthread.com right now. Given all that I'm still dealing with having the second instance of the interpreter unlock the global vm logic so plugins can load in a clean manner. Wow! Which then prints a really big number, later. Great. And yes, it will always involve having the fans go full blast with 4/8 cores. Going forward I need some folks who can compile the VM and do some testing. That is what I can do well. I always find bugs. |
In reply to this post by johnmci
John, can you commit your update to SVN repository, so i can see
what's going on and maybe can be helpful. I don't having Mac, so the only i can help with is the code analysis :) 2008/5/8 John M McIntosh <[hidden email]>: > Ok, a bit more progress. There is still quite a few things to puzzle out. > > I don't want to pound the VM with a ticker update every millisecond. > I don't have a nice way to schedule a wakeup event sometime in the future > by using some generic pthread service. > > I therefore re-implemented the logic that clock checks every message send > and backward jump to > check the current time and consider the next wakeup time. Likely we'll have > to tune this, or perhaps 0.5% of > run time devoted to looking at the clock is just good enough programming. > > Given all that I'm still dealing with having the second instance of the > interpreter unlock the global vm logic so plugins can load in a clean > manner. > I did stick in a change where it does halt the 2nd instance when there is > no squeak process runnable and no pending Delay but that isn't a correct > solution. > > However I now am at the point where I can do > > HydraVM loadAndRunNewImage: 'test.image' > > HydraVM doIt: 'Transcript show: 10000 factorial' at: 2 > > Which then prints a really big number, later. > I can of course interact with the main interpreter instance, and also do > the 10000 factorial, > which then makes my machine run at 200% cpu and whirl the fans to high. > > > Going forward I need some folks who can compile the VM and do some testing. > > > Also I still have to do a sanity check and review all the global & static > variable usage in the mac specific code, and the drawing isn't correct, > menu's get drawn with full transparency. > > -- > =========================================================================== > John M. McIntosh <[hidden email]> > Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com > =========================================================================== > > > > -- Best regards, Igor Stasenko AKA sig. |
On May 7, 2008, at 5:54 PM, Igor Stasenko wrote: > John, can you commit your update to SVN repository, so i can see > what's going on and maybe can be helpful. > I don't having Mac, so the only i can help with is the code > analysis :) Likely tomorrow once I sort thru what I did. However this code is flawed, we end up with ioEnqueueEventInto looping forever given just the right interactions between the main vm and the secondary VM. Perhaps someone can suggest something better, so I'll live it as an exercise to the reader to figure out why it doesn't work as desired. Note I just coded up a ioMutexLock(eventQueueLock); where eventQueueLock is a non-recursive mutex to work around the issue by fully guarding all the code in ioEnqueueEventInto and ioDequeueEventFrom // The OSAtomicCompareAndSwap() operations compare oldValue to *theValue, and set *theValue to newValue if // the comparison is equal. The comparison and assignment occur as one atomic operation. bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); int32_t AtomicCAS(volatile int32_t *__theValue, int32_t __newValue,int32_t __oldValue); int32_t AtomicCAS(volatile int32_t *__theValue, volatile int32_t __newValue,volatile int32_t __oldValue) { volatile int32_t old = *__theValue; OSAtomicCompareAndSwap32Barrier(__oldValue, __newValue,__theValue ); return old; } /* from os-x man OSAtomicCompareAndSwap32Barrier These functions are thread and multiprocessor safe. For each function, there is a version that does and another that does not incorporate a memory barrier. Barriers strictly order memory access on a weakly-ordered architecture such as PPC. All loads and stores executed in sequential program order before the barrier will complete before any load or store executed after the barrier. On a uniproces-sor, uniprocessor, sor, the barrier operation is typically a nop. On a multiprocessor, the barrier can be quite expen-sive. expensive. sive. Most code will want to use the barrier functions to insure that memory shared between threads is prop-erly properly erly synchronized. For example, if you want to initialize a shared data structure and then atomically increment a variable to indicate that the initialization is complete, then you must use OSAtomicIncre-ment32Barrier() OSAtomicIncrement32Barrier() ment32Barrier() to ensure that the stores to your data structure complete before the atomic add. Like-wise, Likewise, wise, the consumer of that data structure must use OSAtomicDecrement32Barrier(), in order to ensure that their loads of the structure are not executed before the atomic decrement. On the other hand, if you are simply incrementing a global counter, then it is safe and potentially much faster to use OSAtomicIncrement32(). If you are unsure which version to use, prefer the barrier variants as they are safer. */ /* on windows this is #define AtomicCAS(value_ptr, new_value, comparand) InterlockedCompareExchange(value_ptr Destination , new_value Exchange, comparand Comparand) Destination A pointer to the destination value. The sign is ignored. Exchange The exchange value. The sign is ignored. Comparand The value to compare to Destination. The sign is ignored. Return Value The function returns the initial value of the Destination parameter. Remarks The function compares the Destination value with the Comparand value. If the Destination value is equal to the Comparand value, the Exchange value is stored in the address specified by Destination. Otherwise, no operation is performed. The parameters for this function must be aligned on a 32-bit boundary; otherwise, the function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems. The interlocked functions provide a simple mechanism for synchronizing access to a variable that is shared by multiple threads. This function is atomic with respect to calls to other interlocked functions. This function is implemented using a compiler intrinsic where possible. For more information, see the header file and _InterlockedCompareExchange. This function generates a full memory barrier (or fence) to ensure that memory operations are completed in order. */ void ioInitEventQueue(struct vmEventQueue * queue) { queue->head.next = 0; queue->tail = &queue->head; } void ioEnqueueEventInto(struct vmEvent * event , struct vmEventQueue * queue) { struct vmEvent * tail; struct vmEvent * old_next; /* add event to tail */ event->next = 0; do { tail = queue->tail; old_next = (struct vmEvent *)AtomicCAS(&tail->next, event, 0); if (old_next != 0) { AtomicCAS(&queue->tail, old_next, tail); } } while (old_next != 0); AtomicCAS(&queue->tail, event, tail); } struct vmEvent * ioDequeueEventFrom(struct vmEventQueue * queue) { struct vmEvent * event; struct vmEvent * oldhead; do { event = queue->head.next; if (!event) { return 0; } oldhead = (struct vmEvent *)AtomicCAS(&queue->head.next, event- >next, event); } while (oldhead != event); /* To prevent queue damage, when queue tail points to just dequeued event, we should replace tail with head */ if (event->next == 0) { /* queue->head.next should be 0, put it as tail */ if ( 0 == AtomicCAS(&event->next, &queue->head, 0)) { AtomicCAS(&queue->tail, &queue->head, event); } } return event; } -- = = = ======================================================================== John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ======================================================================== |
Free forum by Nabble | Edit this page |