Bug in sleep() function - main thread work affecting sleep duration on running tasks

Here you have the version with work being replaced by Libc.systemsleep. Spoiler - it behaves the same: sleep internals are messing things up for the sleep function (the exact same outcome as the OP MWE version).

using Base.Threads, Dates

@info "started with $(nthreads()) threads"
@info "interactive threadpool: $(nthreads(:interactive))"
@info "default threadpool: $(nthreads(:default))"
println(repeat("*", 40))

function mainspin(s, c; withyield=false)
    @info "mainspin executing on thread $(threadid()) "
    r = 0.0
    counter = 0
    while counter < c
        Libc.systemsleep(s)
        counter += 1
        if withyield
            yield()
        end
    end
end

function sleeper(s, c, id)
    @info "sleeper $id executing on thread $(threadid()) "
    counter = 0
    @time "sleeper $id" while counter < c
        sleep(s)
        counter += 1
    end
end

function libcworker(s, c, id)
    @info "worker $id executing on thread $(threadid()) "
    r = 0.0
    counter = 0
    @time "worker $id" while counter < c
        Libc.systemsleep(s)
        counter += 1
        yield()
    end
end

begin
    # phase 1
    @info "phase 1: control run - no main thread work"

    # yields 10 times (total time ~10 seconds)
    task1 = @spawn libcworker(1.02, 10, 1) # 1.02 because weird @time printing overlap
    # yields 10 times (total time ~10 seconds)
    task11 = @spawn sleeper(1, 10, 1)

    wait(task1)
    wait(task11)

    # we waited for task1 and task11 to finish

    # phase 2
    println(repeat("*", 40))
    @info "phase 2: main thread work without yield"

    # yields 10 times (total time ~10 seconds)
    task2 = @spawn libcworker(1, 10, 2)

    # yields 10 times (total time ~10 seconds)
    task22 = @spawn sleeper(1, 10, 2)

    # we wait 5 seconds before starting to spin
    # the main thread
    sleep(5)

    # now we start spinning 
    # while task2 and task22 are already running
    mainspin(1, 7)


    # main thread work does not impact the real worker
    # total time ~10 seconds
    wait(task2)

    # main thread work heavily impacting the sleeper
    # total time >15 seconds
    wait(task22)

    # phase 3
    println(repeat("*", 40))
    @info "phase 3: main thread work with yield"

    # yields 10 times (total time ~10 seconds)
    task3 = @spawn libcworker(1, 10, 3)

    # yields 10 times (total time ~10 seconds)
    task33 = @spawn sleeper(1, 10, 3)

    # we wait 5 seconds before starting to spin
    # the main thread
    sleep(5)

    # now we start spinning with yield
    # while task3 and task33 are running
    mainspin(1, 7, withyield=true)


    # main thread work does not impact 
    # the real worker - total time ~10 seconds
    wait(task3)

    # main thread work (with yield) still impacting the sleeper
    # but we consistently get better times (total time ~13 seconds)
    wait(task33)
end

Outcome with Libc.systemsleep:

[ Info: started with 12 threads
[ Info: interactive threadpool: 6
[ Info: default threadpool: 12
****************************************
[ Info: phase 1: control run - no main thread work
[ Info: worker 1 executing on thread 7 
[ Info: sleeper 1 executing on thread 8 
sleeper 1: 10.020645 seconds (55 allocations: 1.562 KiB)
worker 1: 10.203365 seconds (7.26 k allocations: 535.814 KiB, 0.38% compilation time)
****************************************
[ Info: phase 2: main thread work without yield
[ Info: sleeper 2 executing on thread 16 
[ Info: worker 2 executing on thread 9 
[ Info: mainspin executing on thread 1 
worker 2: 10.004138 seconds (12.28 k allocations: 864.277 KiB, 0.22% compilation time)
sleeper 2: 16.967642 seconds (12.34 k allocations: 867.816 KiB, 0.13% compilation time)
****************************************
[ Info: phase 3: main thread work with yield
[ Info: worker 3 executing on thread 7 
[ Info: sleeper 3 executing on thread 9 
[ Info: mainspin executing on thread 1 
worker 3: 10.003031 seconds (37.10 k allocations: 2.621 MiB, 0.07% compilation time)
sleeper 3: 14.002402 seconds (2.67 k allocations: 249.821 KiB, 0.05% compilation time)