Is there anyway one kernel thread can switch between compute intensive tasks?

Paul Sandoz paul.sandoz at oracle.com
Thu Jan 25 19:17:32 UTC 2018


I dunno much about how Go compiles down to machine code and what the sys libraries do, but as Alan points out the I/O of printing (sys call) could result in the yielding of the goroutine.

See here for some more details:

  http://www.sarathlakshman.com/2016/06/15/pitfall-of-golang-scheduler

"Golang add hooks into runtime provided constructs, libraries and system call wrappers which can make a co-operative call into the scheduler. As it avoids the timers for calling into the scheduler, mutual help from the runtime provided functions are used as entry points into the scheduler. What happens if we managed to write a go-routine that does not use any runtime provides wrapper functions ? This is exactly what has happened here. That go-routine will not calling into the scheduler and cause preemption of the go-routine.”

"Even though the chances of occurring this issue is very rare, but still it could occur. The solution for this problem is to forcefully call into the scheduler from the program in such scenarios. The runtime.Gosched() call facilitates to force enter into the scheduler.”


Another possible place for yielding is a safe-point for GC, which might be placed just before the back branch of a loop and that place could be used, based on a counter, to decide whether to yield or not (not clear if this is really important given the use-cases.)

Paul.

> On Jan 25, 2018, at 10:58 AM, kant kodali <kanth909 at gmail.com> wrote:
> 
> Hi Alan,
> 
> Vow..you got it. Below is the Go code. Can you please explain a bit more on
> how and why Kernel thread yields only for Printf? Does it not yield for any
> other call? can we achieve the same using the Java code (just using kernel
> threads) in my previous email? I am setting GOMAXPROCS=1 such that it is
> equivalent to Java version.
> 
> 
> package main
> 
> import (
>   "fmt"
>   "time"
>   "runtime"
> )
> 
> var tasks = 3
> 
> func main() {
>   runtime.GOMAXPROCS(1)
>   counters := make([]int, tasks)
>   for i := 0; i < tasks; i++ {
>      go func(counter *int) {
>         for {
>            (*counter)++
>            fmt.Print("")
>         }
>      }(&counters[i])
>   }
>   for {
>      time.Sleep(time.Second)
>      fmt.Printf("%#v\n", counters)
>   }
> }
> 
> 
> 
> 
> On Thu, Jan 25, 2018 at 6:30 AM, Alan Bateman <Alan.Bateman at oracle.com>
> wrote:
> 
>> On 25/01/2018 09:51, kant kodali wrote:
>> 
>> :
>> 
>> 
>> If you actually run the program the count will only change for one job but
>> not for all three jobs. But if I use green threads in Golang and assign
>> each green thread an infinite loop they are able to switch however what I
>> don't understand is that once a green thread assigns a kernel thread to run
>> one infinite loop how come other green threads were able to schedule on the
>> same kernel thread? can someone enlighten me here? Sorry if my question is
>> naive.
>> 
>> Is your equivalent in Go using Printf in the loop? I don't know the Go
>> runtime but that is one possible place for a kernel thread to yield. There
>> is also the GOMAXPROCS variable to control the number of kernel threads
>> that run concurrently.
>> 
>> -Alan.
>> 



More information about the loom-dev mailing list