tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: racy acccess in kern_runq.c



Hi,

Thank you for your comment.

On 2019/12/06 16:42, Maxime Villard wrote:
Le 06/12/2019 à 07:52, Kengo NAKAHARA a écrit :
Hi,

There are some racy accesses in kern_runq.c detected by KCSAN.  Those
racy access messages is so frequency that they cover other messages,
so I want to fix them.  They can be fixed by the following patch.

====================
diff --git a/sys/kern/kern_runq.c b/sys/kern/kern_runq.c
index 04ff1732016..bb0815689cd 100644
--- a/sys/kern/kern_runq.c
+++ b/sys/kern/kern_runq.c
@@ -627,7 +627,7 @@ sched_balance(void *nocallout)
      /* Make lockless countings */
      for (CPU_INFO_FOREACH(cii, ci)) {
          spc = &ci->ci_schedstate;
-
+        spc_lock(ci);
          /*
           * Average count of the threads
           *
@@ -643,10 +643,11 @@ sched_balance(void *nocallout)
              hci = ci;
              highest = spc->spc_avgcount;
          }
+        spc_unlock(ci);
      }
     /* Update the worker */
-    worker_ci = hci;
+    atomic_swap_ptr(&worker_ci, hci);
     if (nocallout == NULL)
          callout_schedule(&balance_ch, balance_period);
@@ -734,12 +735,15 @@ sched_idle(void)
      spc_unlock(ci);
 no_migration:
+    spc_lock(ci);
      if ((spc->spc_flags & SPCF_OFFLINE) != 0 || spc->spc_count != 0) {
+        spc_unlock(ci);
          return;
      }
     /* Reset the counter, and call the balancer */
      spc->spc_avgcount = 0;
+    spc_unlock(ci);
      sched_balance(ci);
      tci = worker_ci;
      tspc = &tci->ci_schedstate;
====================

It just so happens we were talking about this yesterday.

Oh, I missed the thread, sorry.

worker_ci indeed needs to be a real atomic, but it means we also have to
fetch it atomically here:

744 	tci = worker_ci;

For the other variables, my understanding was that we don't care about
races, but only care about making sure the accesses are not split, so it
seems to me atomic_relaxed would suffice.

I see.  I update the patch.
====================
diff --git a/sys/kern/kern_runq.c b/sys/kern/kern_runq.c
index 04ff1732016..dbd0f73585a 100644
--- a/sys/kern/kern_runq.c
+++ b/sys/kern/kern_runq.c
@@ -627,6 +627,7 @@ sched_balance(void *nocallout)
 	/* Make lockless countings */
 	for (CPU_INFO_FOREACH(cii, ci)) {
 		spc = &ci->ci_schedstate;
+		u_int avg, mcount;
/*
 		 * Average count of the threads
@@ -634,19 +635,20 @@ sched_balance(void *nocallout)
 		 * The average is computed as a fixpoint number with
 		 * 8 fractional bits.
 		 */
-		spc->spc_avgcount = (
-			weight * spc->spc_avgcount + (100 - weight) * 256 * spc->spc_mcount
-			) / 100;
+		avg = atomic_load_relaxed(&spc->spc_avgcount);
+		mcount = atomic_load_relaxed(&spc->spc_mcount);
+		avg = (weight * avg + (100 - weight) * 256 * mcount) / 100;
+		atomic_store_relaxed(&spc->spc_avgcount, avg);
/* Look for CPU with the highest average */
-		if (spc->spc_avgcount > highest) {
+		if (avg > highest) {
 			hci = ci;
-			highest = spc->spc_avgcount;
+			highest = avg;
 		}
 	}
/* Update the worker */
-	worker_ci = hci;
+	atomic_swap_ptr(&worker_ci, hci);
if (nocallout == NULL)
 		callout_schedule(&balance_ch, balance_period);
@@ -734,14 +736,15 @@ sched_idle(void)
 	spc_unlock(ci);
no_migration:
-	if ((spc->spc_flags & SPCF_OFFLINE) != 0 || spc->spc_count != 0) {
+	if ((spc->spc_flags & SPCF_OFFLINE) != 0
+	    || atomic_load_relaxed(&spc->spc_count) != 0) {
 		return;
 	}
/* Reset the counter, and call the balancer */
-	spc->spc_avgcount = 0;
+	atomic_store_relaxed(&spc->spc_avgcount, 0);
 	sched_balance(ci);
-	tci = worker_ci;
+	atomic_swap_ptr(&tci, worker_ci);
 	tspc = &tci->ci_schedstate;
 	if (ci == tci || spc->spc_psid != tspc->spc_psid)
 		return;
====================

Is this appropriate?


Thanks,

--
//////////////////////////////////////////////////////////////////////
Internet Initiative Japan Inc.

Device Engineering Section,
Product Development Department,
Product Division,
Technology Unit

Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost>


Home | Main Index | Thread Index | Old Index