tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Introducing localcount(9)
Hi,
On 2017/05/12 7:04, Paul Goyette wrote:
> On Thu, 11 May 2017, Taylor R Campbell wrote:
>
>>>> (1) Why splsoftserial() is required instead of kpreempt_disable()?
>>>> localcount_drain() uses xc_broadcast(0, ...), that is, it uses
>>>> low priority xcall. Low priority xcall would be done by kthread
>>>> context, so I think kpreempt_disable() would be sufficient to
>>>> prevent localcount_drain() xcall running.
>>>
>>> I think you are correct. Taylor, do you agree?
>>
>> Yes, I think this is fine. I probably chose splsoftserial because I
>> was thinking of pserialize(9).
>
> Committed.
Thank you for your commit. I believe this modification make it
more efficient. :)
>>>> (2) Why both "localcount_adjust(lc, -1)" and "*lc->lc_totalp -= 1" are
>>>> necessary in "lc->lc_totalp != NULL" case?
>>>> I am afraid of below situation
>>>> [1] CPU#A: mutex_enter(interlock)
>>>> [2] CPU#A: call localcount_drain()
>>>> [3] CPU#A: mutex_exit(interlock) before xc_broadcast
>>>> [4] CPU#B: call localcount_release()
>>>> [5] CPU#B: mutex_enter(interlock)
>>>> [6] CPU#B: localcount_adjust(lc, -1)
>>>> [7] CPU#B: *lc->lc_totalp -= 1
>>>> [8] CPU#B: done localcount_release()
>>>> [9] CPU#A: call xc_broadcast()
>>>> [10]CPU#B: begin localcount_xc() and done
>>>> [11]CPU#A: resume localcount_drain()
>>>> [12]CPU#A: mutex_enter(interlock)
>>>> Can "lc->lc_totalp" be -1 at this point?
>>>
>>> localcount_adjust() updates the local CPU's reference counter, while
>>> *lc->lc_totalp is the global sum that we are accumulating. We want to
>>> keep them synchronized.
>>
>> What knakahara is worried about -- rightly, I think -- is the
>> difference between the following two scenarios:
>>
>> 1. CPU A: localcount_drain (total=0, a=0, b=1)
>> CPU B: localcount_xc (total=1, a=0, b=1)
>> CPU B: localcount_release (total=0, a=0, b=0)
>>
>> 2. CPU A: localcount_drain (total=0, a=0, b=1)
>> CPU B: localcount_release (total=-1, a=0, b=0)
>> CPU B: localcount_xc (total=-1, a=0, b=0)
>>
>> If localcount_xc has already run on the local CPU, then we do want to
>> keep them in sync in localcount_release, which is why I wrote the
>> logic I did. But if it has not yet run, we don't want to double-count
>> the release in the global and the local counts, which is what
>> knakahara observed.
>
> Ah, yes, got it!
I am sorry for lack of words...
Thank you for more clearly explanation, riastradh@n.o!
>> The problem is that in localcount_release, we don't know whether the
>> total includes the local count yet, and thus whether when subtracting
>> one from the local count we also need to subtract one from the total
>> count.
>>
>> One possible way to remedy this -- haven't thought this through yet,
>> obviously needs more attention -- is to change localcount_xc to
>> *transfer* rather than add the local references,
>>
>> mutex_enter(interlock);
>> localp = percpu_getref(lc->lc_percpu);
>> *lc->lc_totalp += *localp;
>> *localp -= *localp; /* i.e., *localp = 0 */
>> percpu_putref(lc->lc_percpu);
>> mutex_exit(interlock);
>>
>> and to change localcount_release to decrement only the total count
>> when it is available:
>>
>> mutex_enter(interlock);
>> if (--*lc->lc_totalp == 0)
>> cv_broadcast(cv);
>> mutex_exit(interlock);
>>
>> Then the scenarios become:
>>
>> 1'. CPU A: localcount_drain (total=0, a=0, b=1)
>> CPU B: localcount_xc (total=1, a=0, b=0)
>> CPU B: localcount_release (total=0, a=0, b=0)
>>
>> 2'. CPU A: localcount_drain (total=0, a=0, b=1)
>> CPU B: localcount_release (total=-1, a=0, b=1)
>> CPU B: localcount_xc (total=0, a=0, b=0)
>
> Makes sense. I've made appropriate changes, and will rebuild and
> re-test.
LGTM, too. Thank you for your fixing.
Thanks,
--
//////////////////////////////////////////////////////////////////////
Internet Initiative Japan Inc.
Device Engineering Section,
IoT Platform Development Department,
Network Division,
Technology Unit
Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost>
Home |
Main Index |
Thread Index |
Old Index