[erlang-questions] : Subtle behaviour of Erlang scheduler

KatolaZ <>
Thu May 31 11:24:44 CEST 2007


On Wed, May 30, 2007 at 01:36:35AM +0200, Rickard Green wrote:

For the sake of clarity:

- I'm just trying to understand if is there any chance of having a
better behaviour of erlang scheduler for high prio processes. This
because I want to try to include (somehow) hard real-time process
support in Erlang (at least for OSes which support them!) :-)

- I'm not trying to miscreditate the work of OTP group, or of other
developers which have been working on Erlang in the last years. Their
work is fundamental for the community and real appreciable :-)

...but...

> >So, just for the purpose of discussion, why don't think at "virtual"
> >synchronisation points for high priority procs ? I.e., if a high
> >priority task has not been interrupted for X reductions (beeing X a
> >relatively large integer), then goto do_schedule1 anyway, letting
> >other high priority process to run....
> 
> If I understood you right, you want the scheduling to work as it is
> implemented right now.
> 
> Regardless of priority, a process is unconditionally scheduled out when
> it has consumed (currently) 2000 reductions (since it was last scheduled
> in). I.e., a busy loop in a high priority process will not prevent other
> high priority processes from running, but it will prevent normal and low
> priority processes from running.
> 

Unfortunately, it seems to be false, or I'm missing something!  Here
is a simple example where all code for high prio processes is loaded
(it is indeed a self-contained module!), and proc_high2 is starved by
proc_high:

-------------
-module(new_test).

-compile(export_all).

test(Max, Prio, Prio2) ->
    process_flag(priority, high),
    register(proc_high, spawn(fun() -> cpu_proc(Max, true, Prio) end)),
    register(proc_high2, spawn(fun() -> high_proc(Prio2) end)).

high_proc(Prio) ->
    process_flag (priority, Prio),
    count(0).

cpu_func(X, Limit) ->
    if 
        (X == Limit) ->
            X;
        true ->
            cpu_func(X+1, Limit)
    end.


cpu_proc(Limit, Send, Prio) ->
    process_flag (priority, Prio),
    Value = cpu_func(0, Limit),
    case Send of 
        true ->
            proc_high2 ! x,
            io:format("OK! Proc ~p exiting at ~p~n", [self(), Value]),
            ok;
        _ ->
            ok
    end.

count (X) ->
    receive
        _ -> io:format ("Process ~p exiting after ~p cycles~n", [process_info (self(), registered_name), X])
    after 0 ->
            count (X + 1)
    end.
-------

then, executing that code I obtain:

Eshell V5.5.2  (abort with ^G)
1> c(new_test).
{ok,new_test}
2> new_test:test(10000000, normal, normal).
true
OK! Proc <0.37.0> exiting at 10000000
Process {registered_name,proc_high2} exiting after 9998992 cycles
3> new_test:test(10000000, high, high).    
OK! Proc <0.40.0> exiting at 10000000
Process {registered_name,proc_high2} exiting after 0 cycles
true
4> 

-------

I.e, if both processes are executed with normal prio, all works, even
if proc_high does not have explicit synchronisation points. When both
processes are executed with prio high, the second process is starved
(it executes for 0 cycles....).  Additionally, if you swap the two
calls to "register", i.e. launching proc_high2 *before* proc_high,
also the shell is starved, and the system *blocks* (you've to CTRL+C
the shell...)

So, I'm probably missing something, but high prio processes without
explicit synchronisation point seem to be *non-preemptible* at
all......

HND

Enzo

-- 
[ Enzo Nicosia aka KatolaZ --- GLUG Catania -- Freaknet Medialab ]
[ me [at] katolaz.homeunix.net -- http://katolaz.homeunix.net -- ]
[ GNU/Linux User:#325780/ICQ UIN: #258332181/GPG key ID 0B5F062F ]
[ Fingerprint: 8E59 D6AA 445E FDB4 A153 3D5A 5F20 B3AE 0B5F 062F ]



More information about the erlang-questions mailing list