[PATCH] cobalt/select: replace APC with irq_work

Chen, Hongzhan hongzhan.chen at intel.com
Tue Sep 29 04:19:05 CEST 2020


>On 24.09.20 08:54, hongzha1 wrote:
>> schedule irq_work which is to schedule work to execute heavy
>> xnselector_destroy_loop instead of calling __xnapc_schedule.
>> 
>> Signed-off-by: hongzha1 <hongzhan.chen at intel.com>
>> 
>> ---
>> this patch is for wip/dovetail. This is new version. It would
>> schedule irq_work which is to schedule work to execute heavy
>> xnselector_destroy_loop but not execute it in irq_work directly
>> instead of calling __xnapc_schedule. 
>>
>What is the benefit of this indirection to a workqueue? irq_work - as
>hardened by dovetail for triggering from oob / xenomai context - still
>run the work in in-band / Linux context, just in an interrupt. IIRC,
>that is the same with the previous APC mechanism, so a 1:1 match.
>
Hi Jan,

My purpose is to keep running short in interrupt context and do the
main work later in work thread in linux. In this case,  schedule_work running 
in irq_work would be very short but at least shorter than running 
xnselector_destroy_loop directly. In addition, xnselector_destroy_loop
seems doing lots of things including xnsynch_destroy and xnfree involving
page remove and xnsched_run in a loop. That is why I try to make it run
in work thread.

>> 
>> diff --git a/kernel/cobalt/select.c b/kernel/cobalt/select.c
>> index c3a3d34b7..69eed626e 100644
>> --- a/kernel/cobalt/select.c
>> +++ b/kernel/cobalt/select.c
>> @@ -23,7 +23,75 @@
>>  #include <cobalt/kernel/sched.h>
>>  #include <cobalt/kernel/synch.h>
>>  #include <cobalt/kernel/select.h>
>> -#include <cobalt/kernel/apc.h>
>> +#include <linux/irq_work.h>
>> +
>> +static bool cobalt_select_isinit;
>> +static LIST_HEAD(xnselect_work_queue);
>> +
>> +typedef void (*cobalt_select_destroy_t) (void *cookie);
>> +
>> +struct cobalt_select_work {
>> +	cobalt_select_destroy_t handler;
>> +	void *arg;
>> +	struct work_struct destroy_task;
>> +};
>> +
>> +typedef struct cobalt_select_work cobalt_select_work_t;
>> +
>> +static cobalt_select_work_t xndeletion_work;
>> +
>> +static void do_xnselect_work(struct irq_work *work)
>> +{
>> +	struct work_struct *xnselect_work;
>> +	spl_t s;
>> +
>> +	xnlock_get_irqsave(&nklock, s);
>> +	while (!list_empty(&xnselect_work_queue)) {
>> +		xnselect_work = list_first_entry(&xnselect_work_queue,
>> +						struct work_struct, entry);
>> +		list_del_init(&xnselect_work->entry);
>> +		xnlock_put_irqrestore(&nklock, s);
>> +		
>> +		schedule_work(xnselect_work);
>> +
>> +		xnlock_get_irqsave(&nklock, s);
>> +
>> +	}
>> +	xnlock_put_irqrestore(&nklock, s);
>> +
>> +}
>> +
>> +static DEFINE_IRQ_WORK(xnselect_irq_work, do_xnselect_work);
>> +
>> +typedef void (*cobalt_select_destroy_t)(void *cookie);
>> +
>> +void xnselect_schedule_work(struct work_struct *destroy_work)
>> +{
>> +	spl_t s;
>> +
>> +	xnlock_get_irqsave(&nklock, s);
>> +	list_add_tail(&xnselect_work_queue, &destroy_work->entry);
>> +	xnlock_put_irqrestore(&nklock, s);
>> +
>> +	irq_work_queue(&xnselect_irq_work);
>> +}
>> +
>> +static void cobalt_select_execute(struct work_struct *work)
>> +{
>> +	cobalt_select_work_t *xnselect =
>> +		container_of(work, cobalt_select_work_t, destroy_task);
>> +	xnselect->handler(xnselect->arg);
>> +}
>> +
>> +int cobalt_select_init(cobalt_select_work_t *xnselect,
>> +		cobalt_select_destroy_t handler, void *arg)
>> +{
>> +	xnselect->handler = handler;
>> +	xnselect->arg = arg;
>> +	INIT_WORK(&xnselect->destroy_task, cobalt_select_execute);
>> +	return 0;
>> +}
>> +
>>  
>>  /**
>>   * @ingroup cobalt_core
> @@ -49,7 +117,6 @@
>>   */
>>  
>>  static LIST_HEAD(selector_list);
>> -static int deletion_apc;
>>  
>>  /**
>>   * Initialize a @a struct @a xnselect structure.
>> @@ -399,9 +466,10 @@ void xnselector_destroy(struct xnselector *selector)
>>  
>>  	xnlock_get_irqsave(&nklock, s);
>>  	list_add_tail(&selector->destroy_link, &selector_list);
>> -#warning TODO: irq_work
>> -	//__xnapc_schedule(deletion_apc);
>>  	xnlock_put_irqrestore(&nklock, s);
>> +	if (cobalt_select_isinit == true)
>> +		xnselect_schedule_work(&xndeletion_work.destroy_task);
>> +
>>  }
>>  EXPORT_SYMBOL_GPL(xnselector_destroy);
>>  
>> @@ -444,18 +512,20 @@ out:
>>  
>>  int xnselect_mount(void)
>>  {
>> -#warning TODO: use irq_work
>> -	/*deletion_apc = xnapc_alloc("selector_list_destroy",
>> -				   xnselector_destroy_loop, NULL);
>> -	if (deletion_apc < 0)
>> -		return deletion_apc;*/
>> +	int ret;
>>  
>> -	return 0;
>> +	cobalt_select_isinit = false;
>> +
>> +	ret = cobalt_select_init(&xndeletion_work, xnselector_destroy_loop, NULL);
>> +	if (!ret)
>> +		cobalt_select_isinit = true;
>> +	return ret;
>>  }
>>  
>>  int xnselect_umount(void)
>>  {
>> -	//xnapc_free(deletion_apc);
>> +	cobalt_select_isinit = false;
>> +	cancel_work_sync(&xndeletion_work.destroy_task);
>>  	return 0;
>>  }
>>  
>> 
>
>OK, so this replaced v2 sent to the list?
>
>Please stay on the list with the patches, maybe just mark them
>additionally with "[dovetail]" or so.

OK. Sorry for the inconvenience.

>Jan
>
>PS: Sorry, I'm late with replying.
>
>-- 

Regards

Hongzhan Chen


More information about the Xenomai mailing list