[5/5] eal: simplify eal alarm cancel by using LIST_FOREACH_SAFE

Message ID 20240808194756.167664-6-stephen@networkplumber.org (mailing list archive)
State Superseded
Delegated to: Thomas Monjalon
Headers
Series alarm related patches |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/github-robot: build fail github build: failed
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-marvell-Functional success Functional Testing PASS
ci/iol-abi-testing warning Testing issues
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS

Commit Message

Stephen Hemminger Aug. 8, 2024, 7:47 p.m. UTC
The code for rte_eal_alarm_cancel was using two loops and duplicate
code to handle cancel at the start of the list. Introduce the
LIST_FOREACH_SAFE() macro from FreeBsd which makes writing
the loop cleaner and simpler.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/linux/eal_alarm.c | 51 +++++++++++++++------------------------
 1 file changed, 19 insertions(+), 32 deletions(-)
  

Comments

Morten Brørup Aug. 9, 2024, 8:33 a.m. UTC | #1
> +++ b/lib/eal/linux/eal_alarm.c
> @@ -53,6 +53,13 @@ static struct rte_intr_handle *intr_handle;
>  static int handler_registered = 0;
>  static void eal_alarm_callback(void *arg);
> 
> +#ifndef LIST_FOREACH_SAFE
> +#define LIST_FOREACH_SAFE(var, head, field, tvar)			\
> +	for ((var) = LIST_FIRST((head));				\
> +	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
> +	    (var) = (tvar))
> +#endif

This macro is already defined for Windows [1]; isn't it also defined in some Linux/BSD standard header file already?

[1]: https://elixir.bootlin.com/dpdk/v24.07/source/lib/eal/windows/include/sys/queue.h#L515
  
Stephen Hemminger Aug. 9, 2024, 3 p.m. UTC | #2
On Fri, 9 Aug 2024 10:33:49 +0200
Morten Brørup <mb@smartsharesystems.com> wrote:

> > +++ b/lib/eal/linux/eal_alarm.c
> > @@ -53,6 +53,13 @@ static struct rte_intr_handle *intr_handle;
> >  static int handler_registered = 0;
> >  static void eal_alarm_callback(void *arg);
> > 
> > +#ifndef LIST_FOREACH_SAFE
> > +#define LIST_FOREACH_SAFE(var, head, field, tvar)			\
> > +	for ((var) = LIST_FIRST((head));				\
> > +	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
> > +	    (var) = (tvar))
> > +#endif  
> 
> This macro is already defined for Windows [1]; isn't it also defined in some Linux/BSD standard header file already?
> 
> [1]: https://elixir.bootlin.com/dpdk/v24.07/source/lib/eal/windows/include/sys/queue.h#L515
> 

Unfortunately, sys/queue.h on Linux is stuck on some old version.
There maybe more complete version on some libbsd headers but don't want
to get into having that dependency.
  

Patch

diff --git a/lib/eal/linux/eal_alarm.c b/lib/eal/linux/eal_alarm.c
index eeb096213b..3f3b722421 100644
--- a/lib/eal/linux/eal_alarm.c
+++ b/lib/eal/linux/eal_alarm.c
@@ -53,6 +53,13 @@  static struct rte_intr_handle *intr_handle;
 static int handler_registered = 0;
 static void eal_alarm_callback(void *arg);
 
+#ifndef LIST_FOREACH_SAFE
+#define LIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = LIST_FIRST((head));				\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+#endif
+
 void
 rte_eal_alarm_cleanup(void)
 {
@@ -194,7 +201,7 @@  rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb_fn, void *cb_arg)
 int
 rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 {
-	struct alarm_entry *ap, *ap_prev;
+	struct alarm_entry *ap, *tmp;
 	int count = 0;
 	int err = 0;
 	int executing;
@@ -207,46 +214,26 @@  rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)
 	do {
 		executing = 0;
 		rte_spinlock_lock(&alarm_list_lk);
-		/* remove any matches at the start of the list */
-		while ((ap = LIST_FIRST(&alarm_list)) != NULL &&
-				cb_fn == ap->cb_fn &&
-				(cb_arg == (void *)-1 || cb_arg == ap->cb_arg)) {
-
-			if (ap->executing == 0) {
-				LIST_REMOVE(ap, next);
-				free(ap);
-				count++;
-			} else {
-				/* If calling from other context, mark that alarm is executing
-				 * so loop can spin till it finish. Otherwise we are trying to
-				 * cancel our self - mark it by EINPROGRESS */
-				if (pthread_equal(ap->executing_id, pthread_self()) == 0)
-					executing++;
-				else
-					err = EINPROGRESS;
-
-				break;
-			}
-		}
-		ap_prev = ap;
 
-		/* now go through list, removing entries not at start */
-		LIST_FOREACH(ap, &alarm_list, next) {
+		LIST_FOREACH_SAFE(ap, &alarm_list, next, tmp) {
 			/* this won't be true first time through */
 			if (cb_fn == ap->cb_fn &&
 					(cb_arg == (void *)-1 || cb_arg == ap->cb_arg)) {
-
 				if (ap->executing == 0) {
 					LIST_REMOVE(ap, next);
 					free(ap);
 					count++;
-					ap = ap_prev;
-				} else if (pthread_equal(ap->executing_id, pthread_self()) == 0)
-					executing++;
-				else
-					err = EINPROGRESS;
+				} else {
+					/* If calling from other context, mark that alarm is executing
+					 * so loop can spin till it finish. Otherwise we are trying to
+					 * cancel our self - mark it by EINPROGRESS
+					 */
+					if (pthread_equal(ap->executing_id, pthread_self()) == 0)
+						executing++;
+					else
+						err = EINPROGRESS;
+				}
 			}
-			ap_prev = ap;
 		}
 		rte_spinlock_unlock(&alarm_list_lk);
 	} while (executing != 0);