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

Konstantin Belousov kostikbel at gmail.com
Thu Aug 7 13:46:25 UTC 2014


On Sun, Jun 22, 2014 at 11:32:23AM +0000, Alexander V. Chernikov wrote:
> Author: melifaro
> Date: Sun Jun 22 11:32:23 2014
> New Revision: 267716
> URL: http://svnweb.freebsd.org/changeset/base/267716
> 
> Log:
>   Permit changing cpu mask for cpu set 1 in presence of drivers
>   binding their threads to particular CPU.
>   
>   Changing ithread cpu mask is now performed by special cpuset_setithread().
>   It creates additional cpuset root group on first bind invocation.
>   
>   No objection:	jhb
>   Tested by:	hiren
>   MFC after:	2 weeks
>   Sponsored by:	Yandex LLC
> 
> Modified:
>   head/sys/kern/kern_cpuset.c
>   head/sys/kern/kern_intr.c
>   head/sys/sys/cpuset.h
> 
> Modified: head/sys/kern/kern_cpuset.c
> ==============================================================================
> --- head/sys/kern/kern_cpuset.c	Sun Jun 22 10:00:33 2014	(r267715)
> +++ head/sys/kern/kern_cpuset.c	Sun Jun 22 11:32:23 2014	(r267716)
> @@ -106,7 +106,7 @@ static uma_zone_t cpuset_zone;
>  static struct mtx cpuset_lock;
>  static struct setlist cpuset_ids;
>  static struct unrhdr *cpuset_unr;
> -static struct cpuset *cpuset_zero;
> +static struct cpuset *cpuset_zero, *cpuset_default;
>  
>  /* Return the size of cpuset_t at the kernel level */
>  SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD,
> @@ -716,6 +716,89 @@ out:
>  }
>  
>  /*
> + * Apply new cpumask to the ithread.
> + */
> +int
> +cpuset_setithread(lwpid_t id, u_char cpu)
> +{
> +	struct cpuset *nset, *rset;
> +	struct cpuset *parent, *old_set;
> +	struct thread *td;
> +	struct proc *p;
> +	cpusetid_t cs_id;
> +	cpuset_t mask;
> +	int error;
> +
> +	nset = uma_zalloc(cpuset_zone, M_WAITOK);
> +	rset = uma_zalloc(cpuset_zone, M_WAITOK);
> +
> +	CPU_ZERO(&mask);
> +	if (cpu == NOCPU)
> +		CPU_COPY(cpuset_root, &mask);
> +	else
> +		CPU_SET(cpu, &mask);
> +
> +	error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &old_set);
> +	if (((cs_id = alloc_unr(cpuset_unr)) == CPUSET_INVALID) || error != 0)
Why calling alloc_unr() at all if error != 0 ?

> +		goto out;
> +
> +	thread_lock(td);
> +	old_set = td->td_cpuset;
> +
> +	if (cpu == NOCPU) {
> +		/*
> +		 * roll back to default set. We're not using cpuset_shadow()
> +		 * here because we can fail CPU_SUBSET() check. This can happen
> +		 * if default set does not contain all CPUs.
> +		 */
> +		error = _cpuset_create(nset, cpuset_default, &mask,
> +		    CPUSET_INVALID);
Why should _cpuset_create() be called under the thread_lock() taken ?

> +
> +		goto applyset;
> +	}
> +
> +	if (old_set->cs_id == 1 || (old_set->cs_id == CPUSET_INVALID &&
> +	    old_set->cs_parent->cs_id == 1)) {
> +		/* Default mask, we need to use new root set */
> +		error = _cpuset_create(rset, cpuset_zero,
> +		    &cpuset_zero->cs_mask, cs_id);
And this one, does the call need thread_lock ?

> +		if (error != 0) {
Wouldn't this leak thread_lock() ?

> +			PROC_UNLOCK(p);
> +			goto out;
> +		}
> +		rset->cs_flags |= CPU_SET_ROOT;
> +		parent = rset;
> +		rset = NULL;
> +		cs_id = CPUSET_INVALID;
> +	} else {
> +		/* Assume existing set was already allocated by previous call */
> +		parent = td->td_cpuset;
> +		old_set = NULL;
> +	}
> +
> +	error = cpuset_shadow(parent, nset, &mask);
> +applyset:
> +	if (error == 0) {
> +		td->td_cpuset = nset;
> +		sched_affinity(td);
> +		nset = NULL;
> +	}
> +	thread_unlock(td);
> +	PROC_UNLOCK(p);
> +	if (old_set != NULL)
> +		cpuset_rel(old_set);
> +out:
> +	if (nset != NULL)
> +		uma_zfree(cpuset_zone, nset);
> +	if (rset != NULL)
> +		uma_zfree(cpuset_zone, rset);
> +	if (cs_id != CPUSET_INVALID)
> +		free_unr(cpuset_unr, cs_id);
> +	return (error);
> +}
> +
> +
> +/*
>   * Creates the cpuset for thread0.  We make two sets:
>   * 
>   * 0 - The root set which should represent all valid processors in the
> @@ -735,6 +818,7 @@ cpuset_thread0(void)
>  	cpuset_zone = uma_zcreate("cpuset", sizeof(struct cpuset), NULL, NULL,
>  	    NULL, NULL, UMA_ALIGN_PTR, 0);
>  	mtx_init(&cpuset_lock, "cpuset", NULL, MTX_SPIN | MTX_RECURSE);
> +
>  	/*
>  	 * Create the root system set for the whole machine.  Doesn't use
>  	 * cpuset_create() due to NULL parent.
> @@ -747,12 +831,15 @@ cpuset_thread0(void)
>  	set->cs_flags = CPU_SET_ROOT;
>  	cpuset_zero = set;
>  	cpuset_root = &set->cs_mask;
> +
>  	/*
>  	 * Now derive a default, modifiable set from that to give out.
>  	 */
>  	set = uma_zalloc(cpuset_zone, M_WAITOK);
>  	error = _cpuset_create(set, cpuset_zero, &cpuset_zero->cs_mask, 1);
>  	KASSERT(error == 0, ("Error creating default set: %d\n", error));
> +	cpuset_default = set;
> +
>  	/*
>  	 * Initialize the unit allocator. 0 and 1 are allocated above.
>  	 */
> 
> Modified: head/sys/kern/kern_intr.c
> ==============================================================================
> --- head/sys/kern/kern_intr.c	Sun Jun 22 10:00:33 2014	(r267715)
> +++ head/sys/kern/kern_intr.c	Sun Jun 22 11:32:23 2014	(r267716)
> @@ -295,7 +295,6 @@ intr_event_create(struct intr_event **ev
>  int
>  intr_event_bind(struct intr_event *ie, u_char cpu)
>  {
> -	cpuset_t mask;
>  	lwpid_t id;
>  	int error;
>  
> @@ -316,14 +315,9 @@ intr_event_bind(struct intr_event *ie, u
>  	 */
>  	mtx_lock(&ie->ie_lock);
>  	if (ie->ie_thread != NULL) {
> -		CPU_ZERO(&mask);
> -		if (cpu == NOCPU)
> -			CPU_COPY(cpuset_root, &mask);
> -		else
> -			CPU_SET(cpu, &mask);
>  		id = ie->ie_thread->it_thread->td_tid;
>  		mtx_unlock(&ie->ie_lock);
> -		error = cpuset_setthread(id, &mask);
> +		error = cpuset_setithread(id, cpu);
>  		if (error)
>  			return (error);
>  	} else
> @@ -332,14 +326,10 @@ intr_event_bind(struct intr_event *ie, u
>  	if (error) {
>  		mtx_lock(&ie->ie_lock);
>  		if (ie->ie_thread != NULL) {
> -			CPU_ZERO(&mask);
> -			if (ie->ie_cpu == NOCPU)
> -				CPU_COPY(cpuset_root, &mask);
> -			else
> -				CPU_SET(ie->ie_cpu, &mask);
> +			cpu = ie->ie_cpu;
>  			id = ie->ie_thread->it_thread->td_tid;
>  			mtx_unlock(&ie->ie_lock);
> -			(void)cpuset_setthread(id, &mask);
> +			(void)cpuset_setithread(id, cpu);
>  		} else
>  			mtx_unlock(&ie->ie_lock);
>  		return (error);
> 
> Modified: head/sys/sys/cpuset.h
> ==============================================================================
> --- head/sys/sys/cpuset.h	Sun Jun 22 10:00:33 2014	(r267715)
> +++ head/sys/sys/cpuset.h	Sun Jun 22 11:32:23 2014	(r267716)
> @@ -118,6 +118,7 @@ struct cpuset *cpuset_thread0(void);
>  struct cpuset *cpuset_ref(struct cpuset *);
>  void	cpuset_rel(struct cpuset *);
>  int	cpuset_setthread(lwpid_t id, cpuset_t *);
> +int	cpuset_setithread(lwpid_t id, u_char cpu);
>  int	cpuset_create_root(struct prison *, struct cpuset **);
>  int	cpuset_setproc_update_set(struct proc *, struct cpuset *);
>  char	*cpusetobj_strprint(char *, const cpuset_t *);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/svn-src-all/attachments/20140807/88b87240/attachment.sig>


More information about the svn-src-all mailing list