svn commit: r317756 - in head/sys: kern sys

John Baldwin jhb at freebsd.org
Wed May 3 21:05:16 UTC 2017


On Wednesday, May 03, 2017 06:41:08 PM Conrad Meyer wrote:
> Author: cem
> Date: Wed May  3 18:41:08 2017
> New Revision: 317756
> URL: https://svnweb.freebsd.org/changeset/base/317756
> 
> Log:
>   Extend cpuset_get/setaffinity() APIs
>   
>   Add IRQ placement-only and ithread-only API variants. intr_event_bind
>   has been extended with sibling methods, as it has many more callsites in
>   existing code.
>
>   Reviewed by:	kib@, adrian@ (earlier version)
>   Sponsored by:	Dell EMC Isilon
>   Differential Revision:	https://reviews.freebsd.org/D10586
> 
> Modified: head/sys/kern/kern_intr.c
> ==============================================================================
> --- head/sys/kern/kern_intr.c	Wed May  3 17:21:01 2017	(r317755)
> +++ head/sys/kern/kern_intr.c	Wed May  3 18:41:08 2017	(r317756)
> @@ -287,13 +287,11 @@ intr_event_create(struct intr_event **ev
>  /*
>   * Bind an interrupt event to the specified CPU.  Note that not all
>   * platforms support binding an interrupt to a CPU.  For those
> - * platforms this request will fail.  For supported platforms, any
> - * associated ithreads as well as the primary interrupt context will
> - * be bound to the specificed CPU.  Using a cpu id of NOCPU unbinds
> + * platforms this request will fail.  Using a cpu id of NOCPU unbinds
>   * the interrupt event.
>   */
> -int
> -intr_event_bind(struct intr_event *ie, int cpu)
> +static int
> +_intr_event_bind(struct intr_event *ie, int cpu, bool bindirq, bool bindithread)
>  {
>  	lwpid_t id;
>  	int error;
> @@ -313,35 +311,75 @@ intr_event_bind(struct intr_event *ie, i
>  	 * If we have any ithreads try to set their mask first to verify
>  	 * permissions, etc.
>  	 */
> -	mtx_lock(&ie->ie_lock);
> -	if (ie->ie_thread != NULL) {
> -		id = ie->ie_thread->it_thread->td_tid;
> -		mtx_unlock(&ie->ie_lock);
> -		error = cpuset_setithread(id, cpu);
> -		if (error)
> -			return (error);
> -	} else
> -		mtx_unlock(&ie->ie_lock);
> -	error = ie->ie_assign_cpu(ie->ie_source, cpu);
> -	if (error) {
> +	if (bindithread) {
>  		mtx_lock(&ie->ie_lock);
>  		if (ie->ie_thread != NULL) {
> -			cpu = ie->ie_cpu;
>  			id = ie->ie_thread->it_thread->td_tid;
>  			mtx_unlock(&ie->ie_lock);
> -			(void)cpuset_setithread(id, cpu);
> +			error = cpuset_setithread(id, cpu);
> +			if (error)
> +				return (error);
>  		} else
>  			mtx_unlock(&ie->ie_lock);
> +	}
> +	if (bindirq)
> +		error = ie->ie_assign_cpu(ie->ie_source, cpu);
> +	if (error) {
> +		if (bindithread) {

This error block should probably be under 'if (bindirq)' as it only used
to "undo" an ithread binding if an irq binding failed.

> +			mtx_lock(&ie->ie_lock);
> +			if (ie->ie_thread != NULL) {
> +				cpu = ie->ie_cpu;
> +				id = ie->ie_thread->it_thread->td_tid;
> +				mtx_unlock(&ie->ie_lock);
> +				(void)cpuset_setithread(id, cpu);
> +			} else
> +				mtx_unlock(&ie->ie_lock);
> +		}
>  		return (error);
>  	}
>  
> -	mtx_lock(&ie->ie_lock);
> -	ie->ie_cpu = cpu;
> -	mtx_unlock(&ie->ie_lock);
> +	if (bindirq) {
> +		mtx_lock(&ie->ie_lock);
> +		ie->ie_cpu = cpu;
> +		mtx_unlock(&ie->ie_lock);
> +	}

This would then be in the else.  That is, the code structure would be
something like:

  if (bindithread) {
     /* new code to bind ithread */
  }
  if (bindirq) {
     error = ie_assign_cpu();
     if (error) {
        /* undo bind ithread */
     } else {
        /* set ie_cpu */
     }
  }

>  
>  	return (error);
>  }
>  
> +/*
> + * Bind an interrupt event to the specified CPU.  For supported platforms, any
> + * associated ithreads as well as the primary interrupt context will be bound
> + * to the specificed CPU.
> + */
> +int
> +intr_event_bind(struct intr_event *ie, int cpu)
> +{
> +
> +	return (_intr_event_bind(ie, cpu, true, true));
> +}

This is used by new-bus so the wrapper needs to stay.

> +
> +/*
> + * Bind an interrupt event to the specified CPU, but do not bind associated
> + * ithreads.
> + */
> +int
> +intr_event_bind_irqonly(struct intr_event *ie, int cpu)
> +{
> +
> +	return (_intr_event_bind(ie, cpu, true, false));
> +}
> +
> +/*
> + * Bind an interrupt event's ithread to the specified CPU.
> + */
> +int
> +intr_event_bind_ithread(struct intr_event *ie, int cpu)
> +{
> +
> +	return (_intr_event_bind(ie, cpu, false, true));
> +}

These aren't otherwise used?  Perhaps rather than having these wrappers, the
switch in intr_setaffinity() could just call _intr_event_bind() directly
with the right set of booleans?  The compiler will probably simplify
it to the equivalent of:

   _intr_event_bind(ie, cpu, which != CPU_WHICH_ITHREAD,
       which != CPU_WHICH_INTRHANDLER);

-- 
John Baldwin


More information about the svn-src-head mailing list