> - is the handler executed in the goroutine of the target?

That's the idea yes.

> But then how does that interact with the goroutine which is already 
running? Does it only execute when the goroutine is next blocked in a 
select { }, for example? In that case, why not just add a new branch to the 
select?

This does not act as a channel at all, this would be a sort of new 
primitive I suppose?
It would require some help from the scheduler to manage the handling of it, 
but yes it would only happen when the goroutine blocks, sleeps, or is 
otherwise in a state of waiting.
I believe C# uses the underlying OS to achieve something similar: 
https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.interrupt?view=net-6.0
An issue I can see with this now is that it may leave the signallee in an 
unknown or undesired state which could easily lead to bugs.
Additionally, it seems C# uses exceptions to achieve this feat.
Further, the concurrency of Go might be cluttered by adding issues of 
reentrancy into the mix, something that doesn't really occur with 
non-interruptible goroutines.

In any case, I've done some more thinking and decided that my issue would 
currently best be solved with partial usage of something like a `TryMutex`. 
With very careful implementation, I still believe signalling would be a 
valuable addition to the language.

On Thursday, March 17, 2022 at 9:19:26 AM UTC+1 Brian Candler wrote:

> I don't understand the semantics of this.  At what point is the handler 
> function executed and in which goroutine? In other words, when you call `s 
> := sig h 1`:
>
> - is the handler executed in the goroutine of the caller? Then how is it 
> different from `s := h(1)` ?
> - is the handler executed in the goroutine of the target? But then how 
> does that interact with the goroutine which is already running? Does it 
> only execute when the goroutine is next blocked in a select { }, for 
> example? In that case, why not just add a new branch to the select?
> - is the handler executed asynchronously in a completely new goroutine? 
> Then how is it different from this?
>
> go func() { c<-h(1) }
> s := <-c
>
>
> On Thursday, 17 March 2022 at 01:36:50 UTC mumbling...@gmail.com wrote:
>
>> I'm currently working on a project where I emulate a RISC-V processor for 
>> the purpose of using Go when teaching concepts of operating systems.
>> I'd like for the emulator to resemble a "real" processor to the point 
>> that a realistic operating system can be implemented with most of the 
>> interesting challenges that this encompasses.
>> One of these challenges is the management of translation caches across 
>> multiple cores which may sometimes require TLB shootdowns.
>>
>> A quick summary of TLB shootdowns: process P has two threads T1 and T2 
>> that run on cores A and B respectively.
>> When T1 makes a request to deallocate a page, core A has to ensure that 
>> T2 on core B invalidates some cached translations before it marks the page 
>> as free, lest B (executing T2) might find the translation in cache and 
>> write to a page that T2 no longer should have access to.
>>
>> My current approach to this is that instead of using a `sync.Mutex` and 
>> `Lock()`, I have created a custom `UntilLock(f func())` which takes in a 
>> function that should be repeatedly executed until the lock is acquired.
>>
>> Current implementation: https://pastecord.com/hofoloxuru.go
>>
>> Notice that every mutex where a `Lock`-`Unlock`-pair might wrap an 
>> interrupt, has to use the `UntilLock` as a `Lock` might cause the 
>> goroutine to block and never check interrupts.
>> The issue is further complicated if one resource R might be locked in 
>> function F and another resource S is locked in function G.
>> In this case, goroutine A might enter F, successfully acquire R, then 
>> signal goroutine B.
>> At the same time, B enters G, successfully acquires S, then signals 
>> goroutine A.
>> We have a deadlock.
>> This is pretty easily resolved though as we just add the interrupt check 
>> to the loop where F and G wait for the other goroutine to execute their 
>> handlers.
>>
>> An idea came to me though...
>> Life would be much easier if Go had signalling between goroutines.
>> One could extend the syntax as `h := go f() handler` where `handler`
>> would have the signature: `func handler(signal int)`
>> You would then signal it with something like `s := sig h 1` to send a 
>> signal of 1 to the goroutine associated with h.
>>
>> Idea for how code would look with signalling: 
>> https://pastecord.com/qunyqejexo.go
>>
>> This would completely eliminate the issue I am currently facing and 
>> though I'm no expert in the field, I believe Go's scheduler could make the 
>> implementation require very little effort and the overhead would be 
>> practically non-existent.
>> This signalling would look a lot like OS signals and is a powerful 
>> feature that isn't too complex in my opinion.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/88c02d75-0f7c-4700-aca0-7e660178513cn%40googlegroups.com.

Reply via email to