[PATCH 4/5] cyclic: switch to using hlist instead of list

Stefan Roese sr at denx.de
Fri Oct 28 16:06:22 CEST 2022


On 28.10.22 13:50, Rasmus Villemoes wrote:
> A hlist is headed by just a single pointer, so can only be traversed
> forwards, and insertions can only happen at the head (or before/after
> an existing list member). But each list node still consists of two
> pointers, so arbitrary elements can still be removed in O(1).
> 
> This is precisely what we need for the cyclic_list - we never need to
> traverse it backwards, and the order the callbacks appear in the list
> should really not matter.
> 
> One advantage, and the main reason for doing this switch, is that an
> empty list is represented by a NULL head pointer, so unlike a
> list_head, it does not need separate C code to initialize - a
> memset(,0,) of the containing structure is sufficient.
> 
> This is mostly mechanical:
> 
> - The iterators are updated with an h prefix, and the type of the
>    temporary variable changed to struct hlist_node*.
> 
> - Adding/removing is now just hlist_add_head (and not tail) and
>    hlist_del().
> 
> - struct members and function return values updated.
> 
> Signed-off-by: Rasmus Villemoes <rasmus.villemoes at prevas.dk>
> ---
>   cmd/cyclic.c     |  5 +++--
>   common/cyclic.c  | 18 ++++++++++--------
>   include/cyclic.h |  6 +++---
>   3 files changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/cmd/cyclic.c b/cmd/cyclic.c
> index c1bc556aad..97324d8240 100644
> --- a/cmd/cyclic.c
> +++ b/cmd/cyclic.c
> @@ -61,10 +61,11 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, int argc,
>   static int do_cyclic_list(struct cmd_tbl *cmdtp, int flag, int argc,
>   			  char *const argv[])
>   {
> -	struct cyclic_info *cyclic, *tmp;
> +	struct cyclic_info *cyclic;
> +	struct hlist_node *tmp;
>   	u64 cnt, freq;
>   
> -	list_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) {
> +	hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) {
>   		cnt = cyclic->run_cnt * 1000000ULL * 100ULL;
>   		freq = lldiv(cnt, timer_get_us() - cyclic->start_time_us);
>   		printf("function: %s, cpu-time: %lld us, frequency: %lld.%02d times/s\n",
> diff --git a/common/cyclic.c b/common/cyclic.c
> index d6f11b002e..32d9bf0d02 100644
> --- a/common/cyclic.c
> +++ b/common/cyclic.c
> @@ -20,7 +20,7 @@ DECLARE_GLOBAL_DATA_PTR;
>   
>   void hw_watchdog_reset(void);
>   
> -struct list_head *cyclic_get_list(void)
> +struct hlist_head *cyclic_get_list(void)
>   {
>   	return &gd->cyclic->cyclic_list;
>   }
> @@ -47,14 +47,14 @@ struct cyclic_info *cyclic_register(cyclic_func_t func, uint64_t delay_us,
>   	cyclic->name = strdup(name);
>   	cyclic->delay_us = delay_us;
>   	cyclic->start_time_us = timer_get_us();
> -	list_add_tail(&cyclic->list, &gd->cyclic->cyclic_list);
> +	hlist_add_head(&cyclic->list, &gd->cyclic->cyclic_list);
>   
>   	return cyclic;
>   }
>   
>   int cyclic_unregister(struct cyclic_info *cyclic)
>   {
> -	list_del(&cyclic->list);
> +	hlist_del(&cyclic->list);
>   	free(cyclic);
>   
>   	return 0;
> @@ -62,7 +62,8 @@ int cyclic_unregister(struct cyclic_info *cyclic)
>   
>   void cyclic_run(void)
>   {
> -	struct cyclic_info *cyclic, *tmp;
> +	struct cyclic_info *cyclic;
> +	struct hlist_node *tmp;
>   	uint64_t now, cpu_time;
>   
>   	/* Prevent recursion */
> @@ -70,7 +71,7 @@ void cyclic_run(void)
>   		return;
>   
>   	gd->flags |= GD_FLG_CYCLIC_RUNNING;
> -	list_for_each_entry_safe(cyclic, tmp, &gd->cyclic->cyclic_list, list) {
> +	hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic->cyclic_list, list) {
>   		/*
>   		 * Check if this cyclic function needs to get called, e.g.
>   		 * do not call the cyclic func too often
> @@ -118,9 +119,10 @@ void schedule(void)
>   
>   int cyclic_uninit(void)
>   {
> -	struct cyclic_info *cyclic, *tmp;
> +	struct cyclic_info *cyclic;
> +	struct hlist_node *tmp;
>   
> -	list_for_each_entry_safe(cyclic, tmp, &gd->cyclic->cyclic_list, list)
> +	hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic->cyclic_list, list)
>   		cyclic_unregister(cyclic);
>   
>   	return 0;
> @@ -135,7 +137,7 @@ int cyclic_init(void)
>   		return -ENOMEM;
>   
>   	memset(gd->cyclic, '\0', size);
> -	INIT_LIST_HEAD(&gd->cyclic->cyclic_list);
> +	INIT_HLIST_HEAD(&gd->cyclic->cyclic_list);
>   
>   	return 0;
>   }
> diff --git a/include/cyclic.h b/include/cyclic.h
> index 263b74d89b..4a11f9b105 100644
> --- a/include/cyclic.h
> +++ b/include/cyclic.h
> @@ -20,7 +20,7 @@
>    * @cyclic_list: Cylic list node
>    */
>   struct cyclic_drv {
> -	struct list_head cyclic_list;
> +	struct hlist_head cyclic_list;
>   };
>   
>   /**
> @@ -46,7 +46,7 @@ struct cyclic_info {
>   	uint64_t cpu_time_us;
>   	uint64_t run_cnt;
>   	uint64_t next_call;
> -	struct list_head list;
> +	struct hlist_node list;
>   	bool already_warned;
>   };
>   
> @@ -95,7 +95,7 @@ int cyclic_uninit(void);
>    *
>    * @return: pointer to cyclic_list
>    */
> -struct list_head *cyclic_get_list(void);
> +struct hlist_head *cyclic_get_list(void);
>   
>   /**
>    * cyclic_run() - Interate over all registered cyclic functions

Reviewed-by: Stefan Roese <sr at denx.de>
Tested-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan


More information about the U-Boot mailing list