xref: /OK3568_Linux_fs/kernel/drivers/block/paride/Transition-notes (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunLemma 1:
2*4882a593Smuzhiyun	If ps_tq is scheduled, ps_tq_active is 1.  ps_tq_int() can be called
3*4882a593Smuzhiyun	only when ps_tq_active is 1.
4*4882a593SmuzhiyunProof:	All assignments to ps_tq_active and all scheduling of ps_tq happen
5*4882a593Smuzhiyun	under ps_spinlock.  There are three places where that can happen:
6*4882a593Smuzhiyun	one in ps_set_intr() (A) and two in ps_tq_int() (B and C).
7*4882a593Smuzhiyun	Consider the sequnce of these events.  A can not be preceded by
8*4882a593Smuzhiyun	anything except B, since it is under if (!ps_tq_active) under
9*4882a593Smuzhiyun	ps_spinlock.  C is always preceded by B, since we can't reach it
10*4882a593Smuzhiyun	other than through B and we don't drop ps_spinlock between them.
11*4882a593Smuzhiyun	IOW, the sequence is A?(BA|BC|B)*.  OTOH, number of B can not exceed
12*4882a593Smuzhiyun	the sum of numbers of A and C, since each call of ps_tq_int() is
13*4882a593Smuzhiyun	the result of ps_tq execution.  Therefore, the sequence starts with
14*4882a593Smuzhiyun	A and each B is preceded by either A or C.  Moments when we enter
15*4882a593Smuzhiyun	ps_tq_int() are sandwiched between {A,C} and B in that sequence,
16*4882a593Smuzhiyun	since at any time number of B can not exceed the number of these
17*4882a593Smuzhiyun	moments which, in turn, can not exceed the number of A and C.
18*4882a593Smuzhiyun	In other words, the sequence of events is (A or C set ps_tq_active to
19*4882a593Smuzhiyun	1 and schedule ps_tq, ps_tq is executed, ps_tq_int() is entered,
20*4882a593Smuzhiyun	B resets ps_tq_active)*.
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunconsider the following area:
24*4882a593Smuzhiyun	* in do_pd_request1(): to calls of pi_do_claimed() and return in
25*4882a593Smuzhiyun	  case when pd_req is NULL.
26*4882a593Smuzhiyun	* in next_request(): to call of do_pd_request1()
27*4882a593Smuzhiyun	* in do_pd_read(): to call of ps_set_intr()
28*4882a593Smuzhiyun	* in do_pd_read_start(): to calls of pi_do_claimed(), next_request()
29*4882a593Smuzhiyunand ps_set_intr()
30*4882a593Smuzhiyun	* in do_pd_read_drq(): to calls of pi_do_claimed() and next_request()
31*4882a593Smuzhiyun	* in do_pd_write(): to call of ps_set_intr()
32*4882a593Smuzhiyun	* in do_pd_write_start(): to calls of pi_do_claimed(), next_request()
33*4882a593Smuzhiyunand ps_set_intr()
34*4882a593Smuzhiyun	* in do_pd_write_done(): to calls of pi_do_claimed() and next_request()
35*4882a593Smuzhiyun	* in ps_set_intr(): to check for ps_tq_active and to scheduling
36*4882a593Smuzhiyun	  ps_tq if ps_tq_active was 0.
37*4882a593Smuzhiyun	* in ps_tq_int(): from the moment when we get ps_spinlock() to the
38*4882a593Smuzhiyun	  return, call of con() or scheduling ps_tq.
39*4882a593Smuzhiyun	* in pi_schedule_claimed() when called from pi_do_claimed() called from
40*4882a593Smuzhiyun	  pd.c, everything until returning 1 or setting or setting ->claim_cont
41*4882a593Smuzhiyun	  on the path that returns 0
42*4882a593Smuzhiyun	* in pi_do_claimed() when called from pd.c, everything until the call
43*4882a593Smuzhiyun	  of pi_do_claimed() plus the everything until the call of cont() if
44*4882a593Smuzhiyun	  pi_do_claimed() has returned 1.
45*4882a593Smuzhiyun	* in pi_wake_up() called for PIA that belongs to pd.c, everything from
46*4882a593Smuzhiyun	  the moment when pi_spinlock has been acquired.
47*4882a593Smuzhiyun
48*4882a593SmuzhiyunLemma 2:
49*4882a593Smuzhiyun	1) at any time at most one thread of execution can be in that area or
50*4882a593Smuzhiyun	be preempted there.
51*4882a593Smuzhiyun	2) When there is such a thread, pd_busy is set or pd_lock is held by
52*4882a593Smuzhiyun	that thread.
53*4882a593Smuzhiyun	3) When there is such a thread, ps_tq_active is 0 or ps_spinlock is
54*4882a593Smuzhiyun	held by that thread.
55*4882a593Smuzhiyun	4) When there is such a thread, all PIA belonging to pd.c have NULL
56*4882a593Smuzhiyun	->claim_cont or pi_spinlock is held by thread in question.
57*4882a593Smuzhiyun
58*4882a593SmuzhiyunProof:	consider the first moment when the above is not true.
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun(1) can become not true if some thread enters that area while another is there.
61*4882a593Smuzhiyun	a) do_pd_request1() can be called from next_request() or do_pd_request()
62*4882a593Smuzhiyun	   In the first case the thread was already in the area.  In the second,
63*4882a593Smuzhiyun	   the thread was holding pd_lock and found pd_busy not set, which would
64*4882a593Smuzhiyun	   mean that (2) was already not true.
65*4882a593Smuzhiyun	b) ps_set_intr() and pi_schedule_claimed() can be called only from the
66*4882a593Smuzhiyun	   area.
67*4882a593Smuzhiyun	c) pi_do_claimed() is called by pd.c only from the area.
68*4882a593Smuzhiyun	d) ps_tq_int() can enter the area only when the thread is holding
69*4882a593Smuzhiyun	   ps_spinlock and ps_tq_active is 1 (due to Lemma 1).  It means that
70*4882a593Smuzhiyun	   (3) was already not true.
71*4882a593Smuzhiyun	e) do_pd_{read,write}* could be called only from the area.  The only
72*4882a593Smuzhiyun	   case that needs consideration is call from pi_wake_up() and there
73*4882a593Smuzhiyun	   we would have to be called for the PIA that got ->claimed_cont
74*4882a593Smuzhiyun	   from pd.c.  That could happen only if pi_do_claimed() had been
75*4882a593Smuzhiyun	   called from pd.c for that PIA, which happens only for PIA belonging
76*4882a593Smuzhiyun	   to pd.c.
77*4882a593Smuzhiyun	f) pi_wake_up() can enter the area only when the thread is holding
78*4882a593Smuzhiyun	   pi_spinlock and ->claimed_cont is non-NULL for PIA belonging to
79*4882a593Smuzhiyun	   pd.c.  It means that (4) was already not true.
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun(2) can become not true only when pd_lock is released by the thread in question.
82*4882a593Smuzhiyun	Indeed, pd_busy is reset only in the area and thread that resets
83*4882a593Smuzhiyun	it is holding pd_lock.	The only place within the area where we
84*4882a593Smuzhiyun	release pd_lock is in pd_next_buf() (called from within the area).
85*4882a593Smuzhiyun	But that code does not reset pd_busy, so pd_busy would have to be
86*4882a593Smuzhiyun	0 when pd_next_buf() had acquired pd_lock.  If it become 0 while
87*4882a593Smuzhiyun	we were acquiring the lock, (1) would be already false, since
88*4882a593Smuzhiyun	the thread that had reset it would be in the area simulateously.
89*4882a593Smuzhiyun	If it was 0 before we tried to acquire pd_lock, (2) would be
90*4882a593Smuzhiyun	already false.
91*4882a593Smuzhiyun
92*4882a593SmuzhiyunFor similar reasons, (3) can become not true only when ps_spinlock is released
93*4882a593Smuzhiyunby the thread in question.  However, all such places within the area are right
94*4882a593Smuzhiyunafter resetting ps_tq_active to 0.
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun(4) is done the same way - all places where we release pi_spinlock within
97*4882a593Smuzhiyunthe area are either after resetting ->claimed_cont to NULL while holding
98*4882a593Smuzhiyunpi_spinlock, or after not tocuhing ->claimed_cont since acquiring pi_spinlock
99*4882a593Smuzhiyunalso in the area.  The only place where ->claimed_cont is made non-NULL is
100*4882a593Smuzhiyunin the area, under pi_spinlock and we do not release it until after leaving
101*4882a593Smuzhiyunthe area.
102*4882a593Smuzhiyun
103*4882a593SmuzhiyunQED.
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun
106*4882a593SmuzhiyunCorollary 1: ps_tq_active can be killed.  Indeed, the only place where we
107*4882a593Smuzhiyuncheck its value is in ps_set_intr() and if it had been non-zero at that
108*4882a593Smuzhiyunpoint, we would have violated either (2.1) (if it was set while ps_set_intr()
109*4882a593Smuzhiyunwas acquiring ps_spinlock) or (2.3) (if it was set when we started to
110*4882a593Smuzhiyunacquire ps_spinlock).
111*4882a593Smuzhiyun
112*4882a593SmuzhiyunCorollary 2: ps_spinlock can be killed.  Indeed, Lemma 1 and Lemma 2 show
113*4882a593Smuzhiyunthat the only possible contention is between scheduling ps_tq followed by
114*4882a593Smuzhiyunimmediate release of spinlock and beginning of execution of ps_tq on
115*4882a593Smuzhiyunanother CPU.
116*4882a593Smuzhiyun
117*4882a593SmuzhiyunCorollary 3: assignment to pd_busy in do_pd_read_start() and do_pd_write_start()
118*4882a593Smuzhiyuncan be killed.  Indeed, we are not holding pd_lock and thus pd_busy is already
119*4882a593Smuzhiyun1 here.
120*4882a593Smuzhiyun
121*4882a593SmuzhiyunCorollary 4: in ps_tq_int() uses of con can be replaced with uses of
122*4882a593Smuzhiyunps_continuation, since the latter is changed only from the area.
123*4882a593SmuzhiyunWe don't need to reset it to NULL, since we are guaranteed that there
124*4882a593Smuzhiyunwill be a call of ps_set_intr() before we look at ps_continuation again.
125*4882a593SmuzhiyunWe can remove the check for ps_continuation being NULL for the same
126*4882a593Smuzhiyunreason - the value is guaranteed to be set by the last ps_set_intr() and
127*4882a593Smuzhiyunwe never pass it NULL.  Assignements in the beginning of ps_set_intr()
128*4882a593Smuzhiyuncan be taken to callers as long as they remain within the area.
129