Hello again,
I don't know much detail of Processes but i found one thing which i don't like. A calls to suspend/resume can't be nested e.g. suppose given code: proc suspend < -- suspends process proc suspend < -- does nothing proc resume < -- resumes process proc resume < -- unknown i think it would be better to have a suspend counter, which will indicate, how many times process has received #suspend, and resume it only when when counter goes to zero. This is essentially useful when you need to guarantee that process will stay suspended even if it's currently suspended waiting for semaphore signal. I tried to modify a Launcher , to make it following: 1. just before image save, suspend all processes except current one 2. <save image> 3. if we resuming, run scripts/launch methods using provided command line arguments 4. resume all previously suspended processes. As you see, step 4 is counterpart of step 1. In step 3, i need guarantee, that there is no other processes which can interrupt execution of current process by all means before it will finish execution. But due to fact, that processes can't nest #suspend calls, this leads to resume all processes unconditionally in step 4, regardless that some of them are suspended and waiting for semaphore signal. Please, let's not discuss how i can get around that issue. I'd like to hear arguments for and against adding nesting capabilities of suspend/resume methods. -- Best regards, Igor Stasenko AKA sig. |
>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:
Igor> Please, let's not discuss how i can get around that issue. I'd like to Igor> hear arguments for and against adding nesting capabilities of Igor> suspend/resume methods. Because you'll be changing what "resume" means. Right now, I can guarantee that resume gets it going again. If you want to implement "countableSuspend" and "countableResume" in your image, that's fine, but don't change what suspend and resume currently do. Or even more simply, evaluate uninterruptably a test-and-set, noting whether or not you actually had to suspend something, or whether it was already suspended. Then resume only the things you actually suspend. That'd be far easier. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training! |
In reply to this post by Igor Stasenko
On 12/20/07, Igor Stasenko <[hidden email]> wrote:
> This is essentially useful when you need to guarantee that process > will stay suspended even if it's currently suspended waiting for > semaphore signal. Do you mean to say that your processes resume running before their semaphores are signaled? If that's not it, what problem are you really trying to fix here? If you want to keep a process that's waiting for a signal from resuming execution when that signal is sent, you're interfering with signal handling, aren't you? That could cause serious troubles in the long run, and the long run might only be a few seconds. Most of the time, most users want most processes to run at full speed. It sounds like you're trying to change that, possibly idling the CPU; why? Maybe you simply want to do some operation in a high-priority process, so as to keep lower-priority processes from interrupting key parts? Cheers! --Tom Phoenix |
On 20/12/2007, Tom Phoenix <[hidden email]> wrote:
> On 12/20/07, Igor Stasenko <[hidden email]> wrote: > > > This is essentially useful when you need to guarantee that process > > will stay suspended even if it's currently suspended waiting for > > semaphore signal. > > Do you mean to say that your processes resume running before their > semaphores are signaled? > Just try to run given code: | sema proc | sema := Semaphore new. proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. Processor yield. proc suspend. proc resume. This example illustrates, that suspend/resume having an issues, when using semaphores. Why caller needs to have specific knowledge about process (is it waits for semaphore or not) if he just simply wants to temporary suspend it and then resume? > If that's not it, what problem are you really trying to fix here? If > you want to keep a process that's waiting for a signal from resuming > execution when that signal is sent, you're interfering with signal > handling, aren't you? That could cause serious troubles in the long > run, and the long run might only be a few seconds. > No matter what is process doing. This is simply not an excuse. And of course, for people who want that, they are sure that they do what they need to do. Otherwise there will be no need in such discussion. > Most of the time, most users want most processes to run at full speed. > It sounds like you're trying to change that, possibly idling the CPU; > why? > > Maybe you simply want to do some operation in a high-priority process, > so as to keep lower-priority processes from interrupting key parts? > > Cheers! > > --Tom Phoenix > -- Best regards, Igor Stasenko AKA sig. |
>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:
Igor> Just try to run given code: Igor> | sema proc | Igor> sema := Semaphore new. Igor> proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. Igor> Processor yield. Igor> proc suspend. Igor> proc resume. Why did you send resume, when your "suspend" didn't actually suspend it? You should simply note that it's a process that didn't need your babysitting. -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training! |
In reply to this post by Igor Stasenko
On 12/20/07, Igor Stasenko <[hidden email]> wrote:
> | sema proc | > sema := Semaphore new. > proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. > Processor yield. > proc suspend. > proc resume. > > > This example illustrates, that suspend/resume having an issues, when > using semaphores. Well, either that or it illustrates that system classes can be misused. But beauty is in the eye of the beholder. > Why caller needs to have specific knowledge about process (is it waits > for semaphore or not) if he just simply wants to temporary suspend it > and then resume? Turn that around: Why should a caller without specific knowledge about a process (i.e., whether it may be waiting for a critical signal) be allowed to resume it? If you want to suspend and resume _all_ other processes, though, that's the same thing as simply running a higher priority process for a while, isn't it? But it sounds as if you really want to do this. If you're hoping that your changes will be useful outside your own image, I recommend that you don't change #resume or other key messages. I like Randal's suggestion of #countableSuspend, but there are other possibilities. If the resume would happen in the same block as the suspend, you could make it so your code would look something like this: proc whileSuspended: [ "Whatever you need to do while it's suspended" ]. "The proc is back to its original run/suspended state now" If you need to resume from a different block than it was suspended in, things get trickier. One idea would be to have a message with a better name than #resumableSuspend, which would return, let's say, an object of type ResumableProcess. You send that object #resume when you're ready, and it handles the other end of getting the process back the way you want it to be. Good luck with it! --Tom Phoenix |
On 20/12/2007, Tom Phoenix <[hidden email]> wrote:
> On 12/20/07, Igor Stasenko <[hidden email]> wrote: > > > | sema proc | > > sema := Semaphore new. > > proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. > > Processor yield. > > proc suspend. > > proc resume. > > > > > > This example illustrates, that suspend/resume having an issues, when > > using semaphores. > > Well, either that or it illustrates that system classes can be > misused. But beauty is in the eye of the beholder. > > > Why caller needs to have specific knowledge about process (is it waits > > for semaphore or not) if he just simply wants to temporary suspend it > > and then resume? > > Turn that around: Why should a caller without specific knowledge about > a process (i.e., whether it may be waiting for a critical signal) be > allowed to resume it? Because process is object and you allowed to send anything you want :) And its should be an object's responsibility for it's own behavior, not the sender's. And if you want to have processes which not able to suspend/resume, then you make it without these methods or make a subclass with methods doing no-op or throwing an error in this methods. But in current design it placing too much responsibility on caller rather than on implementation. And all of this is against spirit of ST. Why i should learn details about Semaphore when i using Process? Why my code should contain special conditions based on process/semaphore specifics, rather than simply call what i want to be called? > > If you want to suspend and resume _all_ other processes, though, > that's the same thing as simply running a higher priority process for > a while, isn't it? > > But it sounds as if you really want to do this. If you're hoping that > your changes will be useful outside your own image, I recommend that > you don't change #resume or other key messages. I like Randal's > suggestion of #countableSuspend, but there are other possibilities. If > the resume would happen in the same block as the suspend, you could > make it so your code would look something like this: > > proc whileSuspended: [ > "Whatever you need to do while it's suspended" > ]. > "The proc is back to its original run/suspended state now" > > If you need to resume from a different block than it was suspended in, > things get trickier. One idea would be to have a message with a better > name than #resumableSuspend, which would return, let's say, an object > of type ResumableProcess. You send that object #resume when you're > ready, and it handles the other end of getting the process back the > way you want it to be. > > Good luck with it! > > --Tom Phoenix > -- Best regards, Igor Stasenko AKA sig. |
Oh, and btw, can someone say, what wrong with following code?
Is it again, my misuse? ;) | sema proc | sema := Semaphore new. proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. Processor yield. proc isSuspended ifFalse: [ proc suspend. proc resume. ] |
Your interpretation of "suspended" is different from what Squeak means
by it. "Suspended" means: This process cannot be made runnable by either a process switch or a semaphore signal. Cheers, - Andreas Igor Stasenko wrote: > Oh, and btw, can someone say, what wrong with following code? > Is it again, my misuse? ;) > > | sema proc | > sema := Semaphore new. > proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. > Processor yield. > proc isSuspended ifFalse: [ proc suspend. proc resume. ] > > |
On 20/12/2007, Andreas Raab <[hidden email]> wrote:
> Your interpretation of "suspended" is different from what Squeak means > by it. "Suspended" means: This process cannot be made runnable by either > a process switch or a semaphore signal. > Hmm, how it differs from 'cannot be made runnable until it will be resumed by sending #resume message'? In the current implementation a #resume is not a counterpart of #suspend and we all have to pay consequences. The #resume should be no-op if process was not suspended by previous call of #suspend. But currently, by sending #resume to process which waiting for signal causing it to continue running as if signal raised. -- Best regards, Igor Stasenko AKA sig. |
Igor Stasenko wrote:
> On 20/12/2007, Andreas Raab <[hidden email]> wrote: >> Your interpretation of "suspended" is different from what Squeak means >> by it. "Suspended" means: This process cannot be made runnable by either >> a process switch or a semaphore signal. >> > Hmm, how it differs from 'cannot be made runnable until it will be > resumed by sending #resume message'? It is equivalent. In your example the process *could* be made runnable (by the semaphore being signaled) so by this definition it wasn't suspended. > In the current implementation a #resume is not a counterpart of > #suspend and we all have to pay consequences. True. But making them symmetric by changing suspend is not useful. If you wanted to make them symmetric you'd have to change resume so that it puts the process back on the list it was suspended frm. > The #resume should be no-op if process was not suspended by previous > call of #suspend. > But currently, by sending #resume to process which waiting for signal > causing it to continue running as if signal raised. That is a bug and should be fixed. Cheers, - Andreas |
In reply to this post by Igor Stasenko
On Dec 21, 2007 8:09 AM, Igor Stasenko <[hidden email]> wrote:
This code looks wrong. I think what you want is: sema := Semaphore new. proc := [ sema wait. Transcript show: 'Oopsie'. ] fork. proc suspend. sema signal. proc resume. I can't try this code at the moment - I don't have Squeak nearby. Generally, I'd rarely use Process>>suspend in my code. Semaphores provide the behaviour that you want; a Semaphore is a linked list of waiting processes. When you call #wait on a semaphore, your process gets added to the list. When you call #signal, the process at one of the ends of the list (FIFO? LIFO? Can't remember) gets resumed. The effect of #suspend and #resume should have no effect on the signalled/waiting state of a Process. In the Launcher example that you give, it would be okay to use #suspend and #resume, but there shouldn't be anything else in the image which is trying to suspend or resume those processes. Gulik. -- http://people.squeakfoundation.org/person/mikevdg http://gulik.pbwiki.com/ |
In reply to this post by Andreas.Raab
On 20/12/2007, Andreas Raab <[hidden email]> wrote:
> Igor Stasenko wrote: > > On 20/12/2007, Andreas Raab <[hidden email]> wrote: > >> Your interpretation of "suspended" is different from what Squeak means > >> by it. "Suspended" means: This process cannot be made runnable by either > >> a process switch or a semaphore signal. > >> > > Hmm, how it differs from 'cannot be made runnable until it will be > > resumed by sending #resume message'? > > It is equivalent. In your example the process *could* be made runnable > (by the semaphore being signaled) so by this definition it wasn't suspended. > > > In the current implementation a #resume is not a counterpart of > > #suspend and we all have to pay consequences. > > True. But making them symmetric by changing suspend is not useful. If > you wanted to make them symmetric you'd have to change resume so that it > puts the process back on the list it was suspended frm. > > > The #resume should be no-op if process was not suspended by previous > > call of #suspend. > > But currently, by sending #resume to process which waiting for signal > > causing it to continue running as if signal raised. > > That is a bug and should be fixed. > And because of it, i unable to simply do suspend/resume for all running processes regardless of their current state. -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Michael van der Gulik-2
On 20/12/2007, Michael van der Gulik <[hidden email]> wrote:
> > > On Dec 21, 2007 8:09 AM, Igor Stasenko <[hidden email]> wrote: > > > > On 20/12/2007, Tom Phoenix <[hidden email]> wrote: > > > On 12/20/07, Igor Stasenko <[hidden email]> wrote: > > > > > > > This is essentially useful when you need to guarantee that process > > > > will stay suspended even if it's currently suspended waiting for > > > > semaphore signal. > > > > > > Do you mean to say that your processes resume running before their > > > semaphores are signaled? > > > > > > > Just try to run given code: > > > > | sema proc | > > sema := Semaphore new. > > proc := [ sema critical: [ Transcript show: 'Oopsie' ] ] fork. > > Processor yield. > > proc suspend. > > proc resume. > > > > > > > > This code looks wrong. > > I think what you want is: > > sema := Semaphore new. > proc := [ sema wait. Transcript show: 'Oopsie'. ] fork. > proc suspend. > sema signal. > proc resume. > semaphore. > I can't try this code at the moment - I don't have Squeak nearby. > > Generally, I'd rarely use Process>>suspend in my code. Semaphores provide > the behaviour that you want; a Semaphore is a linked list of waiting > processes. When you call #wait on a semaphore, your process gets added to > the list. When you call #signal, the process at one of the ends of the list > (FIFO? LIFO? Can't remember) gets resumed. The effect of #suspend and > #resume should have no effect on the signalled/waiting state of a Process. > > In the Launcher example that you give, it would be okay to use #suspend and > #resume, but there shouldn't be anything else in the image which is trying > to suspend or resume those processes. > suspendedList := OrderedCollection new. (Process allInstances select:[:proc | proc isActiveProcess not and: [ proc isSuspended not ]]) do: [:proc | suspendedList add: proc. proc suspend]. <... do my code...> suspendedList do: [:proc | proc resume ]. But because of semaphores bug, after i sending #resume to processes which waiting on semaphore signal causing them think that signal is received. Btw you can try this code yourself and see how low space watcher pops up scaring you to death :) -- Best regards, Igor Stasenko AKA sig. |
On Dec 21, 2007 10:41 AM, Igor Stasenko <[hidden email]> wrote:
Er... oh, I see. From my point of view (which consists of little format training wrt Process management), you're mis-treating these poor objects. The code would work... but I'd never write code like that. If you want to use #critical:, you should be making the Semaphore with "sema := Semaphore forMutualExclusion". "Processor yield" shouldn't ever be used IMHO. It relies on particular behaviour of the scheduler. In a future version of Squeak when we properly support pthreads or we "improve" the behaviour of the scheduler, your code might not work as expected.
I'll try this when I get home. I do a lot of multithreaded programming in Squeak so its important to me that this stuff works right. Gulik. -- http://people.squeakfoundation.org/person/mikevdg http://gulik.pbwiki.com/ |
> > <snip>
> > No, i'm specially doing Processor yield to make proc start waiting for > > semaphore. > > Er... oh, I see. From my point of view (which consists of little format > training wrt Process management), you're mis-treating these poor objects. > The code would work... but I'd never write code like that. > Oh please. How i can mis-treat them. All what i wanted is to call suspend followed by resume. It's not my fault that it's not works as expected in all cases :) > If you want to use #critical:, you should be making the Semaphore with "sema > := Semaphore forMutualExclusion". > Semaphore forMutualExclusion creates an initially signaled semaphore. If created in that way, it will not expose an issue. > "Processor yield" shouldn't ever be used IMHO. It relies on particular > behaviour of the scheduler. In a future version of Squeak when we properly > support pthreads or we "improve" the behaviour of the scheduler, your code > might not work as expected. > P.S. added a bug report to mantis http://bugs.squeak.org/view.php?id=6822 -- Best regards, Igor Stasenko AKA sig. |
On Dec 21, 2007 11:09 AM, Igor Stasenko <[hidden email]> wrote:
Excellent. I'll be having a look at this in about a week's time (after the silly season) if nobody else has started investigating it. Gulik. -- http://people.squeakfoundation.org/person/mikevdg http://gulik.pbwiki.com/ |
In reply to this post by Andreas.Raab
Hi,
I'm new to squeak, so I'm not sure how all this works in Squeak but I have had occasion to look into how Process, ProcessorScheduler, Semaphore and Delay work in VA Smalltalk. They all work closely together. ProcessorScheduler handles the scheduling, suspending and resuming of Processes. The scheduler keeps a list (an array of queues, one for each priority level) of ready to run processes. A wait on a Semaphore or Delay removes (via #suspend) a process from the ready to run list and keeps track when to add it back (via #resume). In Squeak, Delay uses a Semaphore, so these classes are even more closely tied than in VAST. >> The #resume should be no-op if process was not suspended by previous >> call of #suspend. >> But currently, by sending #resume to process which waiting for signal >> causing it to continue running as if signal raised. > >That is a bug and should be fixed. In VAST resuming a terminated process is a no-op in Squeak it looks like it is an error. In both, resuming a suspended process is a no-op, I don't see the bug here. Again, waiting on a Semaphore or Delay does a #suspend, so sending #resume to a process waiting on a Semaphore or Delay will bring the process out of its suspended state. Changing this behavior would be a big deal and I don't see a good reason for the change. I think that in Squeak #isSuspended (maybe not the best name) will tell you if a process is waiting on a Semaphore or a Delay, if you don't want it to resume prematurely, don't send it a #resume. Lou ----------------------------------------------------------- Louis LaBrunda Keystone Software Corp. SkypeMe callto://PhotonDemon mailto:[hidden email] http://www.Keystone-Software.com |
On 21/12/2007, Louis LaBrunda <[hidden email]> wrote:
> Hi, > > I'm new to squeak, so I'm not sure how all this works in Squeak but I have had > occasion to look into how Process, ProcessorScheduler, Semaphore and Delay work > in VA Smalltalk. They all work closely together. ProcessorScheduler handles > the scheduling, suspending and resuming of Processes. > > The scheduler keeps a list (an array of queues, one for each priority level) of > ready to run processes. A wait on a Semaphore or Delay removes (via #suspend) a > process from the ready to run list and keeps track when to add it back (via > #resume). In Squeak, Delay uses a Semaphore, so these classes are even more > closely tied than in VAST. > > >> The #resume should be no-op if process was not suspended by previous > >> call of #suspend. > >> But currently, by sending #resume to process which waiting for signal > >> causing it to continue running as if signal raised. > > > >That is a bug and should be fixed. > > In VAST resuming a terminated process is a no-op in Squeak it looks like it is > an error. In both, resuming a suspended process is a no-op, I don't see the bug > here. Again, waiting on a Semaphore or Delay does a #suspend, so sending > #resume to a process waiting on a Semaphore or Delay will bring the process out > of its suspended state. Changing this behavior would be a big deal and I don't > see a good reason for the change. > > I think that in Squeak #isSuspended (maybe not the best name) will tell you if a > process is waiting on a Semaphore or a Delay, if you don't want it to resume > prematurely, don't send it a #resume. > semaphore returning false on #isSuspended. And i think it's correct, because a 'waiting' is not the same as being suspended. You may think as if its doing: [ semaphore isSignaled ] whileFalse: []. So, it's should be considered as running. And if we going further on that, then sending #resume on process which waits should be no-op, because its _already_ running. But, if we mark process which waiting on semaphore as suspended, then , obviously it should answer true on #isSuspended (but it's not in current squeak). And btw, this is bad idea - because you will lose real control on when this process will be allowed to awake. It can awake at any time when semaphore is signaled. Ans sometimes, this can be not really what you want! So, i think we should fix the #resume and never assume that process which waiting on semaphore are suspended. 'Waiting' and 'suspending' should be different, IMHO! -- Best regards, Igor Stasenko AKA sig. |
Let me make it clear for the last time.
Waiting is an _action_. And process allowed to perform any _actions_ if it's not suspended. If you suspend process, it should stop performing actions until it receive #resume. As another viewpoint, we can consider waiting for #resume as an action too. But since process can perform only single action at some point of time, it can't perform 'wait for resume' and 'wait for signal' in parallel. -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |