9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
       [not found] <f93786a38200d44b7406b3181b4e2c20@cat-v.org>
@ 2007-04-15  8:06 ` Uriel
  2007-04-15 17:00   ` Uriel
  2007-04-15 17:26   ` Devon H. O'Dell
  0 siblings, 2 replies; 12+ messages in thread
From: Uriel @ 2007-04-15  8:06 UTC (permalink / raw)
  To: 9fans

On Sat, 14 Apr 2007 06:17:24, 9changes@cat-v.org <9changes@cat-v.org> wrote:
>         + # turn on cooperative scheduling (assuming it starts off)
>         + echo coop > /dev/reboot
>  [geoff] --rwxrwxr-x M 121 geoff sys 448 Apr 13 18:06 rc/bin/cpurc.local

What does this do? It is undocumented, and as far as I can tell it
toggles the coopsched var, which is used once in the scheduler code.

Would be nice to know what it does exactly, and why on earth it uses
/dev/reboot. Note that there is no way to check the state of the
variable, so one has no clue if one is enabling or disabling
'coopsched', whatever it does this interface is clearly far from
ideal.

While investigating this I noticed a couple of other undocumented
commands for /dev/reboot that seem more relevant and self-evident but
would still be nice to have documented.

Best wishes

uriel


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15  8:06 ` [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local Uriel
@ 2007-04-15 17:00   ` Uriel
  2007-04-15 17:26   ` Devon H. O'Dell
  1 sibling, 0 replies; 12+ messages in thread
From: Uriel @ 2007-04-15 17:00 UTC (permalink / raw)
  To: 9fans

On 4/15/07, Uriel <uriel99@gmail.com> wrote:
> Note that there is no way to check the state of the
> variable, so one has no clue if one is enabling or disabling
> 'coopsched', whatever it does this interface is clearly far from
> ideal.

Seems that I was overzealous (as usual) in this point, I read the code
but then forgot, dho correctly reminded me that there is a kprint
reporting the new state of coopsched when toggled, but this is still
an ugly, non standard and inconvenient interface.

uriel


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15  8:06 ` [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local Uriel
  2007-04-15 17:00   ` Uriel
@ 2007-04-15 17:26   ` Devon H. O'Dell
  2007-04-15 17:35     ` erik quanstrom
                       ` (2 more replies)
  1 sibling, 3 replies; 12+ messages in thread
From: Devon H. O'Dell @ 2007-04-15 17:26 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

2007/4/15, Uriel <uriel99@gmail.com>:
> On Sat, 14 Apr 2007 06:17:24, 9changes@cat-v.org <9changes@cat-v.org> wrote:
> >         + # turn on cooperative scheduling (assuming it starts off)
> >         + echo coop > /dev/reboot
> >  [geoff] --rwxrwxr-x M 121 geoff sys 448 Apr 13 18:06 rc/bin/cpurc.local
>
> What does this do? It is undocumented, and as far as I can tell it
> toggles the coopsched var, which is used once in the scheduler code.

Additionally, we can't assume it starts off. The value is never
initialized in the C code, so it could be 0, 1, or 382355318. I'm
assuming that kencc zeroes uninitialized variables in the text, but
I'm not sure.

> Would be nice to know what it does exactly, and why on earth it uses
> /dev/reboot. Note that there is no way to check the state of the
> variable, so one has no clue if one is enabling or disabling
> 'coopsched', whatever it does this interface is clearly far from
> ideal.
>
> While investigating this I noticed a couple of other undocumented
> commands for /dev/reboot that seem more relevant and self-evident but
> would still be nice to have documented.

At least this one, as the comment states, turns on cooperative
scheduling. Cooperative scheduling differs from preemptive scheduling
in that it requires the process to schedule itself, instead of rely on
the kernel to preempt it when something of higher priority needs to
run. Only, it seems that the kernel controls this, too.

In runproc() (port/proc.c), we have the test

if(coopsched && (p=m->readied) && p->mach == 0 && p->state==Ready &&
runq[Nrq-1].head==nil && runq[Nrq-2].head == nil)

m->readied is a ready process in the Mach structure. This is set in
ready(), which is called in various places, including when notes and
whatnot are sent to a process so that they can act on them
immediately.

p->mach is a pointer back to a machine structure. I'm assuming this
only gets set when a process is being run. I suppose this test is here
in case another CPU took over running the process.

Additionally, the check requires that the highest two priority run
queues are empty. If all these conditions are satisfied, we'll
schedule the process cooperatively. It seems like this would allow
low-priority processes that have notes to be delivered, or are stuck,
or similar, to run when other workloads have finished and the
scheduler hasn't yet ticked. This would obviously give potentially
better CPU / workload utilization. Which is I guess, what this means.
Seems like Russ wrote it, so it'd be interesting to hear how far off I
am.

> Best wishes
>
> uriel

--dho


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:26   ` Devon H. O'Dell
@ 2007-04-15 17:35     ` erik quanstrom
  2007-04-15 17:37       ` Devon H. O'Dell
  2007-04-15 17:38     ` Russ Cox
  2007-04-15 17:43     ` Devon H. O'Dell
  2 siblings, 1 reply; 12+ messages in thread
From: erik quanstrom @ 2007-04-15 17:35 UTC (permalink / raw)
  To: 9fans

> Additionally, we can't assume it starts off. The value is never
> initialized in the C code, so it could be 0, 1, or 382355318. I'm
> assuming that kencc zeroes uninitialized variables in the text, but
> I'm not sure.

non automatic variables are always initialized to zero unless
explicitly initialized to something else regardless of your version of
c.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:35     ` erik quanstrom
@ 2007-04-15 17:37       ` Devon H. O'Dell
  0 siblings, 0 replies; 12+ messages in thread
From: Devon H. O'Dell @ 2007-04-15 17:37 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

2007/4/15, erik quanstrom <quanstro@coraid.com>:
> > Additionally, we can't assume it starts off. The value is never
> > initialized in the C code, so it could be 0, 1, or 382355318. I'm
> > assuming that kencc zeroes uninitialized variables in the text, but
> > I'm not sure.
>
> non automatic variables are always initialized to zero unless
> explicitly initialized to something else regardless of your version of
> c.

Ok, thanks for the clarification.

--dho


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:26   ` Devon H. O'Dell
  2007-04-15 17:35     ` erik quanstrom
@ 2007-04-15 17:38     ` Russ Cox
  2007-04-15 17:43       ` Uriel
  2007-04-15 20:31       ` Devon H. O'Dell
  2007-04-15 17:43     ` Devon H. O'Dell
  2 siblings, 2 replies; 12+ messages in thread
From: Russ Cox @ 2007-04-15 17:38 UTC (permalink / raw)
  To: 9fans

> Additionally, we can't assume it starts off. The value is never
> initialized in the C code, so it could be 0, 1, or 382355318. I'm
> assuming that kencc zeroes uninitialized variables in the text, but
> I'm not sure.

This is just not true.  Global variables in C are guaranteed
to be zeroed at program start time.

> Would be nice to know what it does exactly, and why on earth it uses
> /dev/reboot. Note that there is no way to check the state of the
> variable, so one has no clue if one is enabling or disabling
> 'coopsched', whatever it does this interface is clearly far from
> ideal.

True enough.  The toggle was only so it could be turned off
easily if it was a bad idea, and so that the difference could
be measured.  But it turned out to be a good idea and I never
got around to removing the cruft.  The cruft is now gone
from sources.

The code it controlled in the scheduler did the following.
If process A readies process B to run (say, by writing to a pipe
that process B is reading) and gives up the cpu before
its time slice is up, then process B inherits the rest of
process A's time slice.

This makes concurrent programs (like pipelines, but also 
threaded programs that do a lot of context switching)
get something closer to their fair share of the cpu when
there is scheduling contention.  Inspired by L4.

Russ



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:26   ` Devon H. O'Dell
  2007-04-15 17:35     ` erik quanstrom
  2007-04-15 17:38     ` Russ Cox
@ 2007-04-15 17:43     ` Devon H. O'Dell
  2007-04-15 17:59       ` Russ Cox
  2 siblings, 1 reply; 12+ messages in thread
From: Devon H. O'Dell @ 2007-04-15 17:43 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

2007/4/15, Devon H. O'Dell <devon.odell@gmail.com>:
> p->mach is a pointer back to a machine structure. I'm assuming this
> only gets set when a process is being run. I suppose this test is here
> in case another CPU took over running the process.

Though, this can't be the case, because m->readied isn't locked when
we come in here, and if we're running MP, wouldn't it be possible
(though unlikely) that another CPU takes the process between the
assignment and the test? Especially if running heavily threaded
applications on MP systems?

> --dho


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:38     ` Russ Cox
@ 2007-04-15 17:43       ` Uriel
  2007-04-15 20:31       ` Devon H. O'Dell
  1 sibling, 0 replies; 12+ messages in thread
From: Uriel @ 2007-04-15 17:43 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

Neat, thanks for the explanation!

uriel

On 4/15/07, Russ Cox <rsc@swtch.com> wrote:
> > Additionally, we can't assume it starts off. The value is never
> > initialized in the C code, so it could be 0, 1, or 382355318. I'm
> > assuming that kencc zeroes uninitialized variables in the text, but
> > I'm not sure.
>
> This is just not true.  Global variables in C are guaranteed
> to be zeroed at program start time.
>
> > Would be nice to know what it does exactly, and why on earth it uses
> > /dev/reboot. Note that there is no way to check the state of the
> > variable, so one has no clue if one is enabling or disabling
> > 'coopsched', whatever it does this interface is clearly far from
> > ideal.
>
> True enough.  The toggle was only so it could be turned off
> easily if it was a bad idea, and so that the difference could
> be measured.  But it turned out to be a good idea and I never
> got around to removing the cruft.  The cruft is now gone
> from sources.
>
> The code it controlled in the scheduler did the following.
> If process A readies process B to run (say, by writing to a pipe
> that process B is reading) and gives up the cpu before
> its time slice is up, then process B inherits the rest of
> process A's time slice.
>
> This makes concurrent programs (like pipelines, but also
> threaded programs that do a lot of context switching)
> get something closer to their fair share of the cpu when
> there is scheduling contention.  Inspired by L4.
>
> Russ
>
>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:43     ` Devon H. O'Dell
@ 2007-04-15 17:59       ` Russ Cox
  2007-04-15 20:34         ` Devon H. O'Dell
  0 siblings, 1 reply; 12+ messages in thread
From: Russ Cox @ 2007-04-15 17:59 UTC (permalink / raw)
  To: 9fans

>> p->mach is a pointer back to a machine structure. I'm assuming this
>> only gets set when a process is being run. I suppose this test is here
>> in case another CPU took over running the process.
> 
> Though, this can't be the case, because m->readied isn't locked when
> we come in here, and if we're running MP, wouldn't it be possible
> (though unlikely) that another CPU takes the process between the
> assignment and the test? Especially if running heavily threaded
> applications on MP systems?

	/* cooperative scheduling until the clock ticks */
	if((p=m->readied) && p->mach==0 && p->state==Ready
	&& runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){

The tests are:

	p=m->readied
		some process p was last readied on this cpu (Mach)
	
	p->mach == 0
		p is not running on any cpu right now
	
	p->state == Ready
		p is still Ready (waiting to run)
	
	runq[Nrq-1].head == nil && runq[Nrq-2].head == nil
		there are no real-time processes waiting to run

If all those succeed, then the code tries to choose
p to run next.  But it might not -- the next thing that 
happens is

	p = dequeueproc(rq, p);

which can return nil if p has already been grabbed
or even if there is contention for the runq lock.
All the accesses in the if condition are just fine --
they happen without a lock but dequeueproc double-checks
that p is okay to schedule.

If dequeueproc returns nil, then runproc won't pick 
the readied p after all -- it will fall into the regular
scheduling loop to find a process.

Russ



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:38     ` Russ Cox
  2007-04-15 17:43       ` Uriel
@ 2007-04-15 20:31       ` Devon H. O'Dell
  1 sibling, 0 replies; 12+ messages in thread
From: Devon H. O'Dell @ 2007-04-15 20:31 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

2007/4/15, Russ Cox <rsc@swtch.com>:
> > Additionally, we can't assume it starts off. The value is never
> > initialized in the C code, so it could be 0, 1, or 382355318. I'm
> > assuming that kencc zeroes uninitialized variables in the text, but
> > I'm not sure.
>
> This is just not true.  Global variables in C are guaranteed
> to be zeroed at program start time.

I'm stupid.

> > Would be nice to know what it does exactly, and why on earth it uses
> > /dev/reboot. Note that there is no way to check the state of the
> > variable, so one has no clue if one is enabling or disabling
> > 'coopsched', whatever it does this interface is clearly far from
> > ideal.
>
> True enough.  The toggle was only so it could be turned off
> easily if it was a bad idea, and so that the difference could
> be measured.  But it turned out to be a good idea and I never
> got around to removing the cruft.  The cruft is now gone
> from sources.

This means it should probably be removed from cpurc.local, too, right?
I see it's still there on sources (see uriel's original post with
geoff's change).

--dho


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 17:59       ` Russ Cox
@ 2007-04-15 20:34         ` Devon H. O'Dell
  2007-04-17  5:21           ` Russ Cox
  0 siblings, 1 reply; 12+ messages in thread
From: Devon H. O'Dell @ 2007-04-15 20:34 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

2007/4/15, Russ Cox <rsc@swtch.com>:
>         /* cooperative scheduling until the clock ticks */
>         if((p=m->readied) && p->mach==0 && p->state==Ready
>         && runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){
>
> The tests are:
>
>         p=m->readied
>                 some process p was last readied on this cpu (Mach)
>
>         p->mach == 0
>                 p is not running on any cpu right now

Not to be overly annoying, but _is_ it possible that between the
assignment and that test, p->mach is set, indicating another CPU took
over? It just doesn't seem like m->readied is locked, at all; it seems
like another CPU could pick it up in the middle.

>         p->state == Ready
>                 p is still Ready (waiting to run)
>
>         runq[Nrq-1].head == nil && runq[Nrq-2].head == nil
>                 there are no real-time processes waiting to run
>
> If all those succeed, then the code tries to choose
> p to run next.  But it might not -- the next thing that
> happens is
>
>         p = dequeueproc(rq, p);
>
> which can return nil if p has already been grabbed
> or even if there is contention for the runq lock.
> All the accesses in the if condition are just fine --
> they happen without a lock but dequeueproc double-checks
> that p is okay to schedule.
>
> If dequeueproc returns nil, then runproc won't pick
> the readied p after all -- it will fall into the regular
> scheduling loop to find a process.
>
> Russ

Thanks for the low-level explanation. It does really help my understanding.

--dho


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local
  2007-04-15 20:34         ` Devon H. O'Dell
@ 2007-04-17  5:21           ` Russ Cox
  0 siblings, 0 replies; 12+ messages in thread
From: Russ Cox @ 2007-04-17  5:21 UTC (permalink / raw)
  To: 9fans

> Not to be overly annoying, but _is_ it possible that between the
> assignment and that test, p->mach is set, indicating another CPU took
> over? It just doesn't seem like m->readied is locked, at all; it seems
> like another CPU could pick it up in the middle.

Many things are possible.  m->readied is just a hint.
p->mach is just a hint unless you hold the scheduling lock.

That's why dequeueproc double-checks:
    All the accesses in the if condition are just fine --
    they happen without a lock but dequeueproc double-checks
    that p is okay to schedule.

Russ



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2007-04-17  5:21 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <f93786a38200d44b7406b3181b4e2c20@cat-v.org>
2007-04-15  8:06 ` [9fans] Re: [sources] 20070413: /rc/bin/cpurc.local Uriel
2007-04-15 17:00   ` Uriel
2007-04-15 17:26   ` Devon H. O'Dell
2007-04-15 17:35     ` erik quanstrom
2007-04-15 17:37       ` Devon H. O'Dell
2007-04-15 17:38     ` Russ Cox
2007-04-15 17:43       ` Uriel
2007-04-15 20:31       ` Devon H. O'Dell
2007-04-15 17:43     ` Devon H. O'Dell
2007-04-15 17:59       ` Russ Cox
2007-04-15 20:34         ` Devon H. O'Dell
2007-04-17  5:21           ` Russ Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).