Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1204307 > unrolled thread

Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency mask model

Started byJuri Lelli <juri.lelli@arm.com>
First post2015-08-10 16:10 +0200
Last post2015-08-10 17:40 +0200
Articles 8 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Juri Lelli <juri.lelli@arm.com> - 2015-08-10 16:10 +0200
    Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Frederic Weisbecker <fweisbec@gmail.com> - 2015-08-10 16:20 +0200
      Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Peter Zijlstra <peterz@infradead.org> - 2015-08-10 16:30 +0200
        Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Peter Zijlstra <peterz@infradead.org> - 2015-08-10 17:20 +0200
          Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Frederic Weisbecker <fweisbec@gmail.com> - 2015-08-10 17:30 +0200
            Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Juri Lelli <juri.lelli@arm.com> - 2015-08-10 17:50 +0200
            Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Peter Zijlstra <peterz@infradead.org> - 2015-08-10 18:50 +0200
      Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency  mask model Christoph Lameter <cl@linux.com> - 2015-08-10 17:40 +0200

#1204307 — Re: [PATCH 07/10] sched: Migrate sched to use new tick dependency mask model

FromJuri Lelli <juri.lelli@arm.com>
Date2015-08-10 16:10 +0200
SubjectRe: [PATCH 07/10] sched: Migrate sched to use new tick dependency mask model
Message-ID<pVVW1-7v-3@gated-at.bofh.it>
Hi,

On 04/08/15 08:41, Peter Zijlstra wrote:
> On Mon, Aug 03, 2015 at 07:30:32PM +0200, Frederic Weisbecker wrote:
>>> But you've forgotten about SCHED_DEADLINE, we count those in:
>>> rq->dl.dl_nr_running.
>>
>> Indeed. Hmm, there is no preemption between SCHED_DEALINE tasks, right?
>> So I can treat it like SCHED_FIFO.
> 
> Sadly no. Even though EDF has static job priority (once a job is
> activated its priority doesn't change anymore) DEADLINE also has a CBS
> component and that needs the tick regardless, even with a single task.
> 
> So any deadline task running means we cannot stop the tick.

Well, couldn't we stop it when we use hrtick? As start_hrtick_dl() sets
the hrtick to fire at tasks runtime depletion instant.

Thanks,

- Juri

> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1204314

FromFrederic Weisbecker <fweisbec@gmail.com>
Date2015-08-10 16:20 +0200
Message-ID<pVW5I-iZ-21@gated-at.bofh.it>
In reply to#1204307
On Mon, Aug 10, 2015 at 03:02:04PM +0100, Juri Lelli wrote:
> Hi,
> 
> On 04/08/15 08:41, Peter Zijlstra wrote:
> > On Mon, Aug 03, 2015 at 07:30:32PM +0200, Frederic Weisbecker wrote:
> >>> But you've forgotten about SCHED_DEADLINE, we count those in:
> >>> rq->dl.dl_nr_running.
> >>
> >> Indeed. Hmm, there is no preemption between SCHED_DEALINE tasks, right?
> >> So I can treat it like SCHED_FIFO.
> > 
> > Sadly no. Even though EDF has static job priority (once a job is
> > activated its priority doesn't change anymore) DEADLINE also has a CBS
> > component and that needs the tick regardless, even with a single task.
> > 
> > So any deadline task running means we cannot stop the tick.
> 
> Well, couldn't we stop it when we use hrtick? As start_hrtick_dl() sets
> the hrtick to fire at tasks runtime depletion instant.

Hrtick() only does the task tick part of scheduler_tick(). There are
many other things that need to be updated. Cpu load active (which is buggy
with full dynticks btw. because __update_cpu_load() expects nothing else than
regular frequency updates or idle decay. There is also calc_global_load(),
load balancing stuffs.

I considered many times relying on hrtick btw but everyone seem to say it has a lot
of overhead, especially due to clock reprogramming on schedule() calls.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1204324

FromPeter Zijlstra <peterz@infradead.org>
Date2015-08-10 16:30 +0200
Message-ID<pVWfo-uE-17@gated-at.bofh.it>
In reply to#1204314
On Mon, Aug 10, 2015 at 04:16:58PM +0200, Frederic Weisbecker wrote:

> I considered many times relying on hrtick btw but everyone seem to say it has a lot
> of overhead, especially due to clock reprogramming on schedule() calls.

Yeah, I have some vague ideas of how to take out much of that overhead
(tglx will launch frozen sharks at me I suspect), but we cannot get
around the overhead of actually having to program the hardware and that
is still a significant amount on many machines.

Supposedly machines with TSC deadline are better, but I've not tried
to benchmark that.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1204361

FromPeter Zijlstra <peterz@infradead.org>
Date2015-08-10 17:20 +0200
Message-ID<pVX1M-1Ey-11@gated-at.bofh.it>
In reply to#1204324
On Mon, Aug 10, 2015 at 04:28:47PM +0200, Peter Zijlstra wrote:
> On Mon, Aug 10, 2015 at 04:16:58PM +0200, Frederic Weisbecker wrote:
> 
> > I considered many times relying on hrtick btw but everyone seem to say it has a lot
> > of overhead, especially due to clock reprogramming on schedule() calls.
> 
> Yeah, I have some vague ideas of how to take out much of that overhead
> (tglx will launch frozen sharks at me I suspect), but we cannot get
> around the overhead of actually having to program the hardware and that
> is still a significant amount on many machines.
> 
> Supposedly machines with TSC deadline are better, but I've not tried
> to benchmark that.

Basically something along these lines.. which avoids a whole bunch of
hrtimer stuff.

But without fast hardware its all still pointless.

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 76dd4f0da5ca..c279950cb8c3 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -200,6 +200,7 @@ struct hrtimer_cpu_base {
 	unsigned int			nr_retries;
 	unsigned int			nr_hangs;
 	unsigned int			max_hang_time;
+	ktime_t				expires_sched;
 #endif
 	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
 } ____cacheline_aligned;
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 5c7ae4b641c4..be9c0a555eaa 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -68,6 +68,7 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
 	.lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
 	.seq = SEQCNT_ZERO(hrtimer_bases.seq),
+	.expires_sched = { .tv64 = KTIME_MAX, },
 	.clock_base =
 	{
 		{
@@ -460,7 +461,7 @@ static inline void hrtimer_update_next_timer(struct hrtimer_cpu_base *cpu_base,
 static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
 {
 	struct hrtimer_clock_base *base = cpu_base->clock_base;
-	ktime_t expires, expires_next = { .tv64 = KTIME_MAX };
+	ktime_t expires, expires_next = cpu_base->expires_sched;
 	unsigned int active = cpu_base->active_bases;
 
 	hrtimer_update_next_timer(cpu_base, NULL);
@@ -1289,6 +1290,33 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
 
 #ifdef CONFIG_HIGH_RES_TIMERS
 
+void sched_hrtick_set(u64 ns)
+{
+	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
+	ktime_t expires = ktime_add_ns(ktime_get(), ns);
+
+	raw_spin_lock(&cpu_base->lock);
+	cpu_base->expires_sched = expires;
+
+	if (expires.tv64 < cpu_base->expires_next.tv64)
+		hrtimer_force_reprogram(cpu_base, 0);
+
+	raw_spin_unlock(&cpu_base->lock);
+}
+
+void sched_hrtick_cancel(void)
+{
+	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
+
+	raw_spin_lock(&cpu_base->lock);
+	/*
+	 * If the current event was this sched event, eat the superfluous
+	 * interrupt rather than touch the hardware again.
+	 */
+	cpu_base->expires_sched.tv64 = KTIME_MAX;
+	raw_spin_unlock(&cpu_base->lock);
+}
+
 /*
  * High resolution timer interrupt
  * Called with interrupts disabled
@@ -1316,6 +1344,13 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 	 */
 	cpu_base->expires_next.tv64 = KTIME_MAX;
 
+	if (cpu_base->expires_sched.tv64 < now.tv64) {
+		cpu_base->expires_sched.tv64 = KTIME_MAX;
+		raw_spin_unlock(&cpu_base->lock);
+		scheduler_hrtick();
+		raw_spin_lock(&cpu_base->lock);
+	}
+
 	__hrtimer_run_queues(cpu_base, now);
 
 	/* Reevaluate the clock bases for the next expiry */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1204364

FromFrederic Weisbecker <fweisbec@gmail.com>
Date2015-08-10 17:30 +0200
Message-ID<pVXbr-1PV-7@gated-at.bofh.it>
In reply to#1204361
On Mon, Aug 10, 2015 at 05:11:51PM +0200, Peter Zijlstra wrote:
> On Mon, Aug 10, 2015 at 04:28:47PM +0200, Peter Zijlstra wrote:
> > On Mon, Aug 10, 2015 at 04:16:58PM +0200, Frederic Weisbecker wrote:
> > 
> > > I considered many times relying on hrtick btw but everyone seem to say it has a lot
> > > of overhead, especially due to clock reprogramming on schedule() calls.
> > 
> > Yeah, I have some vague ideas of how to take out much of that overhead
> > (tglx will launch frozen sharks at me I suspect), but we cannot get
> > around the overhead of actually having to program the hardware and that
> > is still a significant amount on many machines.
> > 
> > Supposedly machines with TSC deadline are better, but I've not tried
> > to benchmark that.
> 
> Basically something along these lines.. which avoids a whole bunch of
> hrtimer stuff.
> 
> But without fast hardware its all still pointless.
> 
> diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
> index 76dd4f0da5ca..c279950cb8c3 100644
> --- a/include/linux/hrtimer.h
> +++ b/include/linux/hrtimer.h
> @@ -200,6 +200,7 @@ struct hrtimer_cpu_base {
>  	unsigned int			nr_retries;
>  	unsigned int			nr_hangs;
>  	unsigned int			max_hang_time;
> +	ktime_t				expires_sched;
>  #endif
>  	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
>  } ____cacheline_aligned;
> diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
> index 5c7ae4b641c4..be9c0a555eaa 100644
> --- a/kernel/time/hrtimer.c
> +++ b/kernel/time/hrtimer.c
> @@ -68,6 +68,7 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
>  {
>  	.lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
>  	.seq = SEQCNT_ZERO(hrtimer_bases.seq),
> +	.expires_sched = { .tv64 = KTIME_MAX, },
>  	.clock_base =
>  	{
>  		{
> @@ -460,7 +461,7 @@ static inline void hrtimer_update_next_timer(struct hrtimer_cpu_base *cpu_base,
>  static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
>  {
>  	struct hrtimer_clock_base *base = cpu_base->clock_base;
> -	ktime_t expires, expires_next = { .tv64 = KTIME_MAX };
> +	ktime_t expires, expires_next = cpu_base->expires_sched;
>  	unsigned int active = cpu_base->active_bases;
>  
>  	hrtimer_update_next_timer(cpu_base, NULL);
> @@ -1289,6 +1290,33 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
>  
>  #ifdef CONFIG_HIGH_RES_TIMERS
>  
> +void sched_hrtick_set(u64 ns)
> +{
> +	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
> +	ktime_t expires = ktime_add_ns(ktime_get(), ns);
> +
> +	raw_spin_lock(&cpu_base->lock);
> +	cpu_base->expires_sched = expires;
> +
> +	if (expires.tv64 < cpu_base->expires_next.tv64)
> +		hrtimer_force_reprogram(cpu_base, 0);
> +
> +	raw_spin_unlock(&cpu_base->lock);
> +}
> +
> +void sched_hrtick_cancel(void)
> +{
> +	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
> +
> +	raw_spin_lock(&cpu_base->lock);
> +	/*
> +	 * If the current event was this sched event, eat the superfluous
> +	 * interrupt rather than touch the hardware again.
> +	 */
> +	cpu_base->expires_sched.tv64 = KTIME_MAX;
> +	raw_spin_unlock(&cpu_base->lock);
> +}

Well, there could be a more proper way to do this without tying that to the scheduler
tick. This could be some sort of hrtimer_cancel_soft() which more generally cancels a
timer without cancelling the interrupt itself. We might want to still keep track of that
lost interrupt though in case of later clock reprogramming that fits the lost interrupt.
With a field like cpu_base->expires_interrupt. I thought about expires_soft and expires_hard
but I think that terminology is already used :-)

That said that feature at least wouldn't fit nohz full which really wants to avoid spurious
interrupts.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1204377

FromJuri Lelli <juri.lelli@arm.com>
Date2015-08-10 17:50 +0200
Message-ID<pVXuO-2cJ-19@gated-at.bofh.it>
In reply to#1204364
Hi,

On 10/08/15 16:29, Frederic Weisbecker wrote:
> On Mon, Aug 10, 2015 at 05:11:51PM +0200, Peter Zijlstra wrote:
>> On Mon, Aug 10, 2015 at 04:28:47PM +0200, Peter Zijlstra wrote:
>>> On Mon, Aug 10, 2015 at 04:16:58PM +0200, Frederic Weisbecker wrote:
>>>
>>>> I considered many times relying on hrtick btw but everyone seem to say it has a lot
>>>> of overhead, especially due to clock reprogramming on schedule() calls.
>>>
>>> Yeah, I have some vague ideas of how to take out much of that overhead
>>> (tglx will launch frozen sharks at me I suspect), but we cannot get
>>> around the overhead of actually having to program the hardware and that
>>> is still a significant amount on many machines.
>>>
>>> Supposedly machines with TSC deadline are better, but I've not tried
>>> to benchmark that.
>>
>> Basically something along these lines.. which avoids a whole bunch of
>> hrtimer stuff.
>>
>> But without fast hardware its all still pointless.
>>
>> diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
>> index 76dd4f0da5ca..c279950cb8c3 100644
>> --- a/include/linux/hrtimer.h
>> +++ b/include/linux/hrtimer.h
>> @@ -200,6 +200,7 @@ struct hrtimer_cpu_base {
>>  	unsigned int			nr_retries;
>>  	unsigned int			nr_hangs;
>>  	unsigned int			max_hang_time;
>> +	ktime_t				expires_sched;
>>  #endif
>>  	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
>>  } ____cacheline_aligned;
>> diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
>> index 5c7ae4b641c4..be9c0a555eaa 100644
>> --- a/kernel/time/hrtimer.c
>> +++ b/kernel/time/hrtimer.c
>> @@ -68,6 +68,7 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
>>  {
>>  	.lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
>>  	.seq = SEQCNT_ZERO(hrtimer_bases.seq),
>> +	.expires_sched = { .tv64 = KTIME_MAX, },
>>  	.clock_base =
>>  	{
>>  		{
>> @@ -460,7 +461,7 @@ static inline void hrtimer_update_next_timer(struct hrtimer_cpu_base *cpu_base,
>>  static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
>>  {
>>  	struct hrtimer_clock_base *base = cpu_base->clock_base;
>> -	ktime_t expires, expires_next = { .tv64 = KTIME_MAX };
>> +	ktime_t expires, expires_next = cpu_base->expires_sched;
>>  	unsigned int active = cpu_base->active_bases;
>>  
>>  	hrtimer_update_next_timer(cpu_base, NULL);
>> @@ -1289,6 +1290,33 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
>>  
>>  #ifdef CONFIG_HIGH_RES_TIMERS
>>  
>> +void sched_hrtick_set(u64 ns)
>> +{
>> +	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
>> +	ktime_t expires = ktime_add_ns(ktime_get(), ns);
>> +
>> +	raw_spin_lock(&cpu_base->lock);
>> +	cpu_base->expires_sched = expires;
>> +
>> +	if (expires.tv64 < cpu_base->expires_next.tv64)
>> +		hrtimer_force_reprogram(cpu_base, 0);
>> +
>> +	raw_spin_unlock(&cpu_base->lock);
>> +}
>> +
>> +void sched_hrtick_cancel(void)
>> +{
>> +	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
>> +
>> +	raw_spin_lock(&cpu_base->lock);
>> +	/*
>> +	 * If the current event was this sched event, eat the superfluous
>> +	 * interrupt rather than touch the hardware again.
>> +	 */
>> +	cpu_base->expires_sched.tv64 = KTIME_MAX;
>> +	raw_spin_unlock(&cpu_base->lock);
>> +}
> 
> Well, there could be a more proper way to do this without tying that to the scheduler
> tick. This could be some sort of hrtimer_cancel_soft() which more generally cancels a
> timer without cancelling the interrupt itself. We might want to still keep track of that
> lost interrupt though in case of later clock reprogramming that fits the lost interrupt.
> With a field like cpu_base->expires_interrupt. I thought about expires_soft and expires_hard
> but I think that terminology is already used :-)
> 
> That said that feature at least wouldn't fit nohz full which really wants to avoid spurious
> interrupts.
> 

Quite a detailed reply to my naive question :).
Thanks a lot Frederic and Peter for this!

For what concerns SCHED_DEADLINE, I guess the bottom line is
that it makes sense to use hrtick for sub-millisecond accounting
only (without nohz full).

Best,

- Juri

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1204427

FromPeter Zijlstra <peterz@infradead.org>
Date2015-08-10 18:50 +0200
Message-ID<pVYqR-3yH-15@gated-at.bofh.it>
In reply to#1204364
On Mon, Aug 10, 2015 at 05:29:22PM +0200, Frederic Weisbecker wrote:

> Well, there could be a more proper way to do this without tying that
> to the scheduler tick. This could be some sort of
> hrtimer_cancel_soft() which more generally cancels a timer without
> cancelling the interrupt itself.

So when I looked at this last -- a long long time ago -- the whole
hrtimer rbtree took a significant amount of time. Hence the proposal
here to avoid all of it for this special timer.

> We might want to still keep track of
> that lost interrupt though in case of later clock reprogramming that
> fits the lost interrupt.  With a field like
> cpu_base->expires_interrupt. I thought about expires_soft and
> expires_hard but I think that terminology is already used :-)

Its easy enough to 'fix', but typically you'd reprogram a new sched tick
anyway, so its moot. Touching the hardware twice, once to cancel the
old, once to program the new, is double pain.

The only case where you really take that interrupt is when you cancel
and go idle I suppose, and we could special case that if the NOHZ code
doesn't already DTRT (by accident) etc..

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1204371

FromChristoph Lameter <cl@linux.com>
Date2015-08-10 17:40 +0200
Message-ID<pVXl8-21m-19@gated-at.bofh.it>
In reply to#1204314
On Mon, 10 Aug 2015, Frederic Weisbecker wrote:

> I considered many times relying on hrtick btw but everyone seem to say it has a lot
> of overhead, especially due to clock reprogramming on schedule() calls.

Depends on how many ticks you can save I would think. It certainly is
worthwhile if you can avoid 10 ticks? Can we figure out how far in the
future that event is? If its more than 10 ticks away then its worth to
switch off the tick?


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web