From owner-svn-src-head@FreeBSD.ORG Sun Jun 22 11:32:24 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 5248B5D7; Sun, 22 Jun 2014 11:32:24 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 312A82DA4; Sun, 22 Jun 2014 11:32:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s5MBWOJw097087; Sun, 22 Jun 2014 11:32:24 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s5MBWNWj097084; Sun, 22 Jun 2014 11:32:23 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201406221132.s5MBWNWj097084@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Sun, 22 Jun 2014 11:32:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r267716 - in head/sys: kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 22 Jun 2014 11:32:24 -0000 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) + 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); + + 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); + if (error != 0) { + 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 *);