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 *);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to