Added some files to FBSD owned by MOD_SCHED FW.
authorJens Krieg <jkrieg@mailbox.tu-berlin.de>
Mon, 26 May 2014 09:43:50 +0000 (11:43 +0200)
committerJens Krieg <jkrieg@mailbox.tu-berlin.de>
Mon, 26 May 2014 09:43:50 +0000 (11:43 +0200)
sys/amd64/conf/kernel_x86_64-conf
sys/conf/files
sys/conf/ldscript.amd64
sys/kern/sched_ule.c

index 5a7b1ee..5964f60 100644 (file)
@@ -22,7 +22,7 @@ cpu           HAMMER
 ident          KBS-Kernel
 
 makeoptions    DEBUG=-g                # Build kernel with gdb(1) debug symbols
-options                VERBOSE_SYSINIT
+#options               VERBOSE_SYSINIT
 #options               DDB
 options        SCHED_ULE               # ULE scheduler
 options        FW_MOD_SCHED            # Modulized scheduler framework
@@ -71,7 +71,7 @@ options       KDB                     # Kernel debugger related code
 options        KDB_TRACE               # Print a stack trace for a panic
 
 # Make an SMP-capable kernel by default
-#options       SMP                     # Symmetric MultiProcessor Kernel
+options        SMP                     # Symmetric MultiProcessor Kernel
 
 # CPU frequency control
 device         cpufreq
index 3bdbddc..0a923b9 100644 (file)
@@ -3543,15 +3543,21 @@ dev/xen/netfront/netfront.c     optional xen | xenhvm
 dev/xen/xenpci/xenpci.c                optional xenpci
 dev/xen/xenpci/evtchn.c         optional xenpci
 
-framework/lib/fw.c                      optional fw_mod_sched
-framework/lib/fw_modules.c              optional fw_mod_sched
-framework/lib/fw_comm.c                 optional fw_mod_sched
-framework/lib/fw_list.c                 optional fw_mod_sched
-framework/lib/fw_lock.c                 optional fw_mod_sched
-framework/lib/fw_sched.c                optional fw_mod_sched
-framework/modules/round_robin.c         optional fw_mod_sched
-framework/os/freebsd/os.c               optional fw_mod_sched
-framework/os/freebsd/os_kdb.c           optional fw_mod_sched
-framework/os/freebsd/os_lock.c          optional fw_mod_sched
-framework/os/freebsd/os_sched.c         optional fw_mod_sched
-framework/os/freebsd/fbsd_sched.c       optional fw_mod_sched
+framework/generated/fw_comm_generated.c                optional fw_mod_sched
+framework/generated/topo_rr_quad.c                     optional fw_mod_sched
+framework/generated/topo_rr_single.c           optional fw_mod_sched
+framework/lib/fw.c                             optional fw_mod_sched
+framework/lib/fw_comm.c                        optional fw_mod_sched
+framework/lib/fw_debug.c                       optional fw_mod_sched
+framework/lib/fw_list.c                        optional fw_mod_sched
+framework/lib/fw_lock.c                        optional fw_mod_sched
+framework/lib/fw_modules.c                     optional fw_mod_sched
+framework/lib/fw_sched.c                       optional fw_mod_sched
+framework/modules/load_balance.c               optional fw_mod_sched
+framework/modules/round_robin.c                optional fw_mod_sched
+framework/modules/tick_divider.c               optional fw_mod_sched
+framework/os/freebsd/os.c                      optional fw_mod_sched
+framework/os/freebsd/os_kdb.c                  optional fw_mod_sched
+framework/os/freebsd/os_lock.c                 optional fw_mod_sched
+framework/os/freebsd/os_sched.c                optional fw_mod_sched
+framework/os/freebsd/fbsd_sched.c              optional fw_mod_sched
index 9210a73..9586268 100644 (file)
@@ -148,6 +148,14 @@ SECTIONS
   }
   .data1          : { *(.data1) }
   _edata = .; PROVIDE (edata = .);
+  
+  .fw.modules.init . : 
+  {
+       __fw_modules_init_start = .;
+       *(.fw.modules.init)
+       __fw_modules_init_end = .;
+       __data_end = .;
+  } 
   __bss_start = .;
   .bss            :
   {
index a4bb6b6..4e1053a 100644 (file)
 // * Isilon Systems and a general lack of creativity on the part of the author.
 // */
 //
+///*
+// * XXX:      So far we got rid of the real time run queue and the multilevel queues.
+// *                   Timesharing queue is the queue for every task except idle. We also
+// *                   removed dynamic priorities for the timesharing tasks and now they are
+// *                   assigned statically. Removed load tracking.
+// * TODO:     Every timesharing task should have the same priority?
+// *                   Find out how time slice calculation works (nice value, priority or score based?).
+// *                   SMP!!!
+// *
+// * XXX:      SMP case will not compile! Make sure it is disable in kernel config.
+// *
+// */
+//
 //#include <sys/cdefs.h>
 //__FBSDID("$FreeBSD$");
 //
 //#include <sys/cpuset.h>
 //#include <sys/sbuf.h>
 //
-//
-//#include <fw.h>
-//
-//
 //#ifdef HWPMC_HOOKS
 //#include <sys/pmckern.h>
 //#endif
 //#error "This architecture is not currently compatible with ULE"
 //#endif
 //
+//
+//#include <fw.h>
+//
+//
 //#define      KTR_ULE 0
 //
 //#define      TS_NAME_LEN (MAXCOMLEN + sizeof(" td ") + sizeof(__XSTRING(UINT_MAX)))
 //#define      SCHED_AFFINITY_DEFAULT  (max(1, hz / 1000))
 //#define      SCHED_AFFINITY(ts, t)   ((ts)->ts_rltick > ticks - ((t) * affinity))
 //
+///**
+// * Extend thread state macros.
+// */
+//#undef TD_SET_EXITING
+//#define      TD_SET_EXITING(td)      (td)->td_state = TDS_INACTIVE
+//#define      TD_IS_EXITING(td)       (td)->td_state == TDS_INACTIVE
+//
 ///*
 // * Run-time tunables.
 // */
 //#define      TDQ_LOCK_FLAGS(t, f)    mtx_lock_spin_flags(TDQ_LOCKPTR((t)), (f))
 //#define      TDQ_UNLOCK(t)           mtx_unlock_spin(TDQ_LOCKPTR((t)))
 //#define      TDQ_LOCKPTR(t)          (&(t)->tdq_lock)
-//#define      TDQ_IDLESPIN(tdq)       1
 //
 ////static void sched_priority(struct thread *);
 ////static void sched_thread_priority(struct thread *, u_char);
 ////static int sched_balance_pair(struct tdq *, struct tdq *);
 //static inline struct tdq *sched_setcpu(struct thread *, int, int);
 //static inline void thread_unblock_switch(struct thread *, struct mtx *);
-////static struct mtx *sched_switch_migrate(struct tdq *, struct thread *, int);
+//static struct mtx *sched_switch_migrate(struct tdq *, struct thread *, int);
 //static int sysctl_kern_sched_topology_spec(SYSCTL_HANDLER_ARGS);
 //static int sysctl_kern_sched_topology_spec_internal(struct sbuf *sb,
 //    struct cpu_group *cg, int indent);
 //static __inline void
 //tdq_runq_add(struct tdq *tdq, struct thread *td, int flags)
 //{
-////   struct td_sched *ts;
-////   struct fw_queues *q = cpu_queue(0);
-////   struct fw_task *p = &td->td_sched->fw_task;
-////// u_char pri;
-////
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////
-////// pri = td->td_priority;
-////// printf("THREAD PRIORITY %d\n", pri);
-////   ts = td->td_sched;
-////   TD_SET_RUNQ(td);
-////   if (THREAD_CAN_MIGRATE(td)) {
-////           tdq->tdq_transferable++;
-////           ts->ts_flags |= TSF_XFERABLE;
-////   }
-////
-////// if (pri < PRI_MIN_BATCH) {
-//////         ts->ts_runq = &tdq->tdq_realtime;
-////// } else if (pri <= PRI_MAX_BATCH) {
-//////         ts->ts_runq = &tdq->tdq_timeshare;
-//////         KASSERT(pri <= PRI_MAX_BATCH && pri >= PRI_MIN_BATCH,
-//////                 ("Invalid priority %d on timeshare runq", pri));
-//////         /*
-//////          * This queue contains only priorities between MIN and MAX
-//////          * realtime.  Use the whole queue to represent these values.
-//////          */
-//////         if ((flags & (SRQ_BORROWING|SRQ_PREEMPTED)) == 0) {
-//////                 pri = RQ_NQS * (pri - PRI_MIN_BATCH) / PRI_BATCH_RANGE;
-//////                 pri = (pri + tdq->tdq_idx) % RQ_NQS;
-//////                 /*
-//////                  * This effectively shortens the queue by one so we
-//////                  * can have a one slot difference between idx and
-//////                  * ridx while we wait for threads to drain.
-//////                  */
-//////                 if (tdq->tdq_ridx != tdq->tdq_idx &&
-//////                     pri == tdq->tdq_ridx)
-//////                         pri = (unsigned char)(pri - 1) % RQ_NQS;
-//////         } else
-//////                 pri = tdq->tdq_ridx;
-//////         runq_add_pri(ts->ts_runq, td, pri, flags);
-//////         return;
-////// } else
-//////         ts->ts_runq = &tdq->tdq_idle;
-////// runq_add(ts->ts_runq, td, flags);
-////
-////   /* Insert thread at the tail. We have no preemption anyway. */
-////// flags &= ~SRQ_PREEMPTED;
-////
-////// printf("tdq_runq_add\n");
-////// tdq_print(TDQ_ID(tdq));
-////
-////   if (td->td_flags & TDF_IDLETD) {
-////           ts->ts_runq = &tdq->tdq_idle;
-////           runq_add_pri(ts->ts_runq, td, 0, flags);
-////   }
-////   else {
-////
+//     struct td_sched *ts;
+////   u_char pri;
+//
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//
+////   pri = td->td_priority;
+////   printf("THREAD PRIORITY %d\n", pri);
+//     ts = td->td_sched;
+//     TD_SET_RUNQ(td);
+//     if (THREAD_CAN_MIGRATE(td)) {
+//             tdq->tdq_transferable++;
+//             ts->ts_flags |= TSF_XFERABLE;
+//     }
+////   if (pri < PRI_MIN_BATCH) {
+////           ts->ts_runq = &tdq->tdq_realtime;
+////   } else if (pri <= PRI_MAX_BATCH) {
+////           ts->ts_runq = &tdq->tdq_timeshare;
+////           KASSERT(pri <= PRI_MAX_BATCH && pri >= PRI_MIN_BATCH,
+////                   ("Invalid priority %d on timeshare runq", pri));
 ////           /*
-////            * Announce task to framework.
+////            * This queue contains only priorities between MIN and MAX
+////            * realtime.  Use the whole queue to represent these values.
 ////            */
-////           p->real_task = td;
-////           p->state = FW_READY;
-////           fw_notify(FW_ADMIT, (void*)p);
-////
-////           ts->ts_runq = &tdq->tdq_timeshare;
-////           runq_add_pri(ts->ts_runq, td, 0, flags);
-////   }
+////           if ((flags & (SRQ_BORROWING|SRQ_PREEMPTED)) == 0) {
+////                   pri = RQ_NQS * (pri - PRI_MIN_BATCH) / PRI_BATCH_RANGE;
+////                   pri = (pri + tdq->tdq_idx) % RQ_NQS;
+////                   /*
+////                    * This effectively shortens the queue by one so we
+////                    * can have a one slot difference between idx and
+////                    * ridx while we wait for threads to drain.
+////                    */
+////                   if (tdq->tdq_ridx != tdq->tdq_idx &&
+////                       pri == tdq->tdq_ridx)
+////                           pri = (unsigned char)(pri - 1) % RQ_NQS;
+////           } else
+////                   pri = tdq->tdq_ridx;
+////           runq_add_pri(ts->ts_runq, td, pri, flags);
+////           return;
+////   } else
+////           ts->ts_runq = &tdq->tdq_idle;
+////   runq_add(ts->ts_runq, td, flags);
+//
+//     /* Insert thread at the tail. We have no preemption anyway. */
+////   flags &= ~SRQ_PREEMPTED;
+//
+////   printf("tdq_runq_add\n");
+////   tdq_print(TDQ_ID(tdq));
+//
+//     if (td->td_flags & TDF_IDLETD) {
+//             ts->ts_runq = &tdq->tdq_idle;
+//             runq_add_pri(ts->ts_runq, td, 0, flags);
+//     }
+//     else {
+//             if (td->td_flags & TDF_IDLETD) printf("IDLE incomming\n");
+//             ts->ts_runq = &tdq->tdq_timeshare;
+//             runq_add_pri(ts->ts_runq, td, 0, flags);
+//     }
 //}
 //
 ///*
 //static __inline void
 //tdq_runq_rem(struct tdq *tdq, struct thread *td)
 //{
-////   struct td_sched *ts;
-////
-////   ts = td->td_sched;
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   KASSERT(ts->ts_runq != NULL,
-////       ("tdq_runq_remove: thread %p null ts_runq", td));
-////   if (ts->ts_flags & TSF_XFERABLE) {
-////           tdq->tdq_transferable--;
-////           ts->ts_flags &= ~TSF_XFERABLE;
-////   }
-////
-////   if (ts->ts_runq == &tdq->tdq_timeshare) {
-////           if (tdq->tdq_idx != tdq->tdq_ridx)
-////                   runq_remove_idx(ts->ts_runq, td, &tdq->tdq_ridx);
-////           else
-////                   runq_remove_idx(ts->ts_runq, td, NULL);
-////   } else
-////           runq_remove(ts->ts_runq, td);
+//     struct td_sched *ts;
+//
+//     ts = td->td_sched;
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     KASSERT(ts->ts_runq != NULL,
+//         ("tdq_runq_remove: thread %p null ts_runq", td));
+//     if (ts->ts_flags & TSF_XFERABLE) {
+//             tdq->tdq_transferable--;
+//             ts->ts_flags &= ~TSF_XFERABLE;
+//     }
+//     if (ts->ts_runq == &tdq->tdq_timeshare) {
+//             if (tdq->tdq_idx != tdq->tdq_ridx)
+//                     runq_remove_idx(ts->ts_runq, td, &tdq->tdq_ridx);
+//             else
+//                     runq_remove_idx(ts->ts_runq, td, NULL);
+//     } else
+//             runq_remove(ts->ts_runq, td);
 //}
 //
 ///*
 //static void
 //tdq_load_add(struct tdq *tdq, struct thread *td)
 //{
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////
-////   tdq->tdq_load++;
+//
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//
+//     tdq->tdq_load++;
 ////   if ((td->td_flags & TDF_NOLOAD) == 0)
 ////           tdq->tdq_sysload++;
 ////   KTR_COUNTER0(KTR_SCHED, "load", tdq->tdq_loadname, tdq->tdq_load);
 //static void
 //tdq_load_rem(struct tdq *tdq, struct thread *td)
 //{
-////
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   KASSERT(tdq->tdq_load != 0,
-////       ("tdq_load_rem: Removing with 0 load on queue %d", TDQ_ID(tdq)));
-////
-////   tdq->tdq_load--;
+//
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     KASSERT(tdq->tdq_load != 0,
+//         ("tdq_load_rem: Removing with 0 load on queue %d", TDQ_ID(tdq)));
+//
+//     tdq->tdq_load--;
 ////   if ((td->td_flags & TDF_NOLOAD) == 0)
 ////           tdq->tdq_sysload--;
 ////   KTR_COUNTER0(KTR_SCHED, "load", tdq->tdq_loadname, tdq->tdq_load);
 //              * restrictions loop again with this cpu removed from the
 //              * set.
 //              */
-//             if (tdq->tdq_load == 0 && tdq_move(steal, tdq) == 0) {
-//                     tdq_unlock_pair(tdq, steal);
-//                     continue;
-//             }
+////           if (tdq->tdq_load == 0 && tdq_move(steal, tdq) == 0) {
+////                   tdq_unlock_pair(tdq, steal);
+////                   continue;
+////           }
 //             spinlock_exit();
 //             TDQ_UNLOCK(steal);
 //             mi_switch(SW_VOL | SWT_IDLE, NULL);
 //
 //     THREAD_LOCK_ASSERT(td, MA_OWNED);
 //     tdq = TDQ_CPU(cpu);
+//
 //     td->td_sched->ts_cpu = cpu;
 //     /*
 //      * If the lock matches just return the queue.
 //static int
 //sched_pickcpu(struct thread *td, int flags)
 //{
-//     struct cpu_group *cg, *ccg;
-//     struct td_sched *ts;
-//     struct tdq *tdq;
-//     cpuset_t mask;
-//     int cpu, pri, self;
+//     return 0;
 //
-//     self = PCPU_GET(cpuid);
-//     ts = td->td_sched;
-//     if (smp_started == 0)
-//             return (self);
-//     /*
-//      * Don't migrate a running thread from sched_switch().
-//      */
-//     if ((flags & SRQ_OURSELF) || !THREAD_CAN_MIGRATE(td))
-//             return (ts->ts_cpu);
-//     /*
-//      * Prefer to run interrupt threads on the processors that generate
-//      * the interrupt.
-//      */
-//     pri = td->td_priority;
-//     if (td->td_priority <= PRI_MAX_ITHD && THREAD_CAN_SCHED(td, self) &&
-//         curthread->td_intr_nesting_level && ts->ts_cpu != self) {
-//             SCHED_STAT_INC(pickcpu_intrbind);
-//             ts->ts_cpu = self;
-//             if (TDQ_CPU(self)->tdq_lowpri > pri) {
-//                     SCHED_STAT_INC(pickcpu_affinity);
-//                     return (ts->ts_cpu);
-//             }
-//     }
-//     /*
-//      * If the thread can run on the last cpu and the affinity has not
-//      * expired or it is idle run it there.
-//      */
-//     tdq = TDQ_CPU(ts->ts_cpu);
-//     cg = tdq->tdq_cg;
-//     if (THREAD_CAN_SCHED(td, ts->ts_cpu) &&
-//         tdq->tdq_lowpri >= PRI_MIN_IDLE &&
-//         SCHED_AFFINITY(ts, CG_SHARE_L2)) {
-//             if (cg->cg_flags & CG_FLAG_THREAD) {
-//                     CPUSET_FOREACH(cpu, cg->cg_mask) {
-//                             if (TDQ_CPU(cpu)->tdq_lowpri < PRI_MIN_IDLE)
-//                                     break;
-//                     }
-//             } else
-//                     cpu = INT_MAX;
-//             if (cpu > mp_maxid) {
-//                     SCHED_STAT_INC(pickcpu_idle_affinity);
-//                     return (ts->ts_cpu);
-//             }
-//     }
-//     /*
-//      * Search for the last level cache CPU group in the tree.
-//      * Skip caches with expired affinity time and SMT groups.
-//      * Affinity to higher level caches will be handled less aggressively.
-//      */
-//     for (ccg = NULL; cg != NULL; cg = cg->cg_parent) {
-//             if (cg->cg_flags & CG_FLAG_THREAD)
-//                     continue;
-//             if (!SCHED_AFFINITY(ts, cg->cg_level))
-//                     continue;
-//             ccg = cg;
-//     }
-//     if (ccg != NULL)
-//             cg = ccg;
-//     cpu = -1;
-//     /* Search the group for the less loaded idle CPU we can run now. */
-//     mask = td->td_cpuset->cs_mask;
-//     if (cg != NULL && cg != cpu_top &&
-//         CPU_CMP(&cg->cg_mask, &cpu_top->cg_mask) != 0)
-//             cpu = sched_lowest(cg, mask, max(pri, PRI_MAX_TIMESHARE),
-//                 INT_MAX, ts->ts_cpu);
-//     /* Search globally for the less loaded CPU we can run now. */
-//     if (cpu == -1)
-//             cpu = sched_lowest(cpu_top, mask, pri, INT_MAX, ts->ts_cpu);
-//     /* Search globally for the less loaded CPU. */
-//     if (cpu == -1)
-//             cpu = sched_lowest(cpu_top, mask, -1, INT_MAX, ts->ts_cpu);
-//     KASSERT(cpu != -1, ("sched_pickcpu: Failed to find a cpu."));
-//     /*
-//      * Compare the lowest loaded cpu to current cpu.
-//      */
-//     if (THREAD_CAN_SCHED(td, self) && TDQ_CPU(self)->tdq_lowpri > pri &&
-//         TDQ_CPU(cpu)->tdq_lowpri < PRI_MIN_IDLE &&
-//         TDQ_CPU(self)->tdq_load <= TDQ_CPU(cpu)->tdq_load + 1) {
-//             SCHED_STAT_INC(pickcpu_local);
-//             cpu = self;
-//     } else
-//             SCHED_STAT_INC(pickcpu_lowest);
-//     if (cpu != ts->ts_cpu)
-//             SCHED_STAT_INC(pickcpu_migration);
-//     return (cpu);
+////   struct cpu_group *cg, *ccg;
+////   struct td_sched *ts;
+////   struct tdq *tdq;
+////   cpuset_t mask;
+////   int cpu, pri, self;
+////
+////   self = PCPU_GET(cpuid);
+////   ts = td->td_sched;
+////   if (smp_started == 0)
+////           return (self);
+////   /*
+////    * Don't migrate a running thread from sched_switch().
+////    */
+////   if ((flags & SRQ_OURSELF) || !THREAD_CAN_MIGRATE(td))
+////           return (ts->ts_cpu);
+////   /*
+////    * Prefer to run interrupt threads on the processors that generate
+////    * the interrupt.
+////    */
+////   pri = td->td_priority;
+////   if (td->td_priority <= PRI_MAX_ITHD && THREAD_CAN_SCHED(td, self) &&
+////       curthread->td_intr_nesting_level && ts->ts_cpu != self) {
+////           SCHED_STAT_INC(pickcpu_intrbind);
+////           ts->ts_cpu = self;
+////           if (TDQ_CPU(self)->tdq_lowpri > pri) {
+////                   SCHED_STAT_INC(pickcpu_affinity);
+////                   return (ts->ts_cpu);
+////           }
+////   }
+////   /*
+////    * If the thread can run on the last cpu and the affinity has not
+////    * expired or it is idle run it there.
+////    */
+////   tdq = TDQ_CPU(ts->ts_cpu);
+////   cg = tdq->tdq_cg;
+////   if (THREAD_CAN_SCHED(td, ts->ts_cpu) &&
+////       tdq->tdq_lowpri >= PRI_MIN_IDLE &&
+////       SCHED_AFFINITY(ts, CG_SHARE_L2)) {
+////           if (cg->cg_flags & CG_FLAG_THREAD) {
+////                   CPUSET_FOREACH(cpu, cg->cg_mask) {
+////                           if (TDQ_CPU(cpu)->tdq_lowpri < PRI_MIN_IDLE)
+////                                   break;
+////                   }
+////           } else
+////                   cpu = INT_MAX;
+////           if (cpu > mp_maxid) {
+////                   SCHED_STAT_INC(pickcpu_idle_affinity);
+////                   return (ts->ts_cpu);
+////           }
+////   }
+////   /*
+////    * Search for the last level cache CPU group in the tree.
+////    * Skip caches with expired affinity time and SMT groups.
+////    * Affinity to higher level caches will be handled less aggressively.
+////    */
+////   for (ccg = NULL; cg != NULL; cg = cg->cg_parent) {
+////           if (cg->cg_flags & CG_FLAG_THREAD)
+////                   continue;
+////           if (!SCHED_AFFINITY(ts, cg->cg_level))
+////                   continue;
+////           ccg = cg;
+////   }
+////   if (ccg != NULL)
+////           cg = ccg;
+////   cpu = -1;
+////   /* Search the group for the less loaded idle CPU we can run now. */
+////   mask = td->td_cpuset->cs_mask;
+////   if (cg != NULL && cg != cpu_top &&
+////       CPU_CMP(&cg->cg_mask, &cpu_top->cg_mask) != 0)
+////           cpu = sched_lowest(cg, mask, max(pri, PRI_MAX_TIMESHARE),
+////               INT_MAX, ts->ts_cpu);
+////   /* Search globally for the less loaded CPU we can run now. */
+////   if (cpu == -1)
+////           cpu = sched_lowest(cpu_top, mask, pri, INT_MAX, ts->ts_cpu);
+////   /* Search globally for the less loaded CPU. */
+////   if (cpu == -1)
+////           cpu = sched_lowest(cpu_top, mask, -1, INT_MAX, ts->ts_cpu);
+////   KASSERT(cpu != -1, ("sched_pickcpu: Failed to find a cpu."));
+////   /*
+////    * Compare the lowest loaded cpu to current cpu.
+////    */
+////   if (THREAD_CAN_SCHED(td, self) && TDQ_CPU(self)->tdq_lowpri > pri &&
+////       TDQ_CPU(cpu)->tdq_lowpri < PRI_MIN_IDLE &&
+////       TDQ_CPU(self)->tdq_load <= TDQ_CPU(cpu)->tdq_load + 1) {
+////           SCHED_STAT_INC(pickcpu_local);
+////           cpu = self;
+////   } else
+////           SCHED_STAT_INC(pickcpu_lowest);
+////   if (cpu != ts->ts_cpu)
+////           SCHED_STAT_INC(pickcpu_migration);
+////   return (cpu);
 //}
 //#endif
 //
 //static struct thread *
 //tdq_choose(struct tdq *tdq)
 //{
-////   struct thread *td;
-////
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////
-////   td = runq_choose_from(&tdq->tdq_timeshare, tdq->tdq_ridx);
-////   if (td != NULL) {
-////           return (td);
-////   }
-////   td = runq_choose(&tdq->tdq_idle);
-////   if (td != NULL) {
+//     struct thread *td;
+//
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+////   td = runq_choose(&tdq->tdq_realtime);
+////   if (td != NULL)
 ////           return (td);
-////   }
-////
-////   return (NULL);
+//     td = runq_choose_from(&tdq->tdq_timeshare, tdq->tdq_ridx);
+//     if (td != NULL) {
+////           KASSERT(td->td_priority >= PRI_MIN_BATCH,
+////               ("tdq_choose: Invalid priority on timeshare queue %d",
+////               td->td_priority));
+//             return (td);
+//     }
+//     td = runq_choose(&tdq->tdq_idle);
+//     if (td != NULL) {
+////           KASSERT(td->td_priority >= PRI_MIN_IDLE,
+////               ("tdq_choose: Invalid priority on idle queue %d",
+////               td->td_priority));
+//             return (td);
+//     }
+//
+//     return (NULL);
 //}
 //
 ///*
 //static void
 //tdq_setup(struct tdq *tdq)
 //{
-////   if (bootverbose)
-////           printf("ULE: setup cpu %d\n", TDQ_ID(tdq));
+//
+//     if (bootverbose)
+//             printf("ULE: setup cpu %d\n", TDQ_ID(tdq));
 ////   runq_init(&tdq->tdq_realtime);
-////   runq_init(&tdq->tdq_timeshare);
-////   runq_init(&tdq->tdq_idle);
-////   snprintf(tdq->tdq_name, sizeof(tdq->tdq_name),
-////       "sched lock %d", (int)TDQ_ID(tdq));
-////   mtx_init(&tdq->tdq_lock, tdq->tdq_name, "sched lock",
-////       MTX_SPIN | MTX_RECURSE);
-////#ifdef KTR
-////   snprintf(tdq->tdq_loadname, sizeof(tdq->tdq_loadname),
-////       "CPU %d load", (int)TDQ_ID(tdq));
-////#endif
+//     runq_init(&tdq->tdq_timeshare);
+//     runq_init(&tdq->tdq_idle);
+//     snprintf(tdq->tdq_name, sizeof(tdq->tdq_name),
+//         "sched lock %d", (int)TDQ_ID(tdq));
+//     mtx_init(&tdq->tdq_lock, tdq->tdq_name, "sched lock",
+//         MTX_SPIN | MTX_RECURSE);
+//#ifdef KTR
+//     snprintf(tdq->tdq_loadname, sizeof(tdq->tdq_loadname),
+//         "CPU %d load", (int)TDQ_ID(tdq));
+//#endif
 //}
 //
 //#ifdef SMP
 //     struct tdq *tdq;
 //
 //     tdq = TDQ_SELF();
-//
+//#ifdef SMP
+//     sched_setup_smp();
+//#else
+//     tdq_setup(tdq);
+//#endif
 //     /*
 //      * To avoid divide-by-zero, we set realstathz a dummy value
 //      * in case which sched_clock() called before sched_initticks().
 //     /* Add thread0's load since it's running. */
 //     TDQ_LOCK(tdq);
 //     thread0.td_lock = TDQ_LOCKPTR(TDQ_SELF());
-//     tdq->tdq_load++;
+//     tdq_load_add(tdq, &thread0);
+////   tdq->tdq_lowpri = thread0.td_priority;
 //     TDQ_UNLOCK(tdq);
 //}
 //
 //void
 //schedinit(void)
 //{
+//     struct fw_data *fwd;
+//
 //     /*
 //      * Set up the scheduler specific parts of proc0.
 //      */
 //     proc0.p_sched = NULL; /* XXX */
 //     thread0.td_sched = &td_sched0;
+//     td_sched0.fw_task.real_task = &thread0;
 //     td_sched0.ts_ltick = ticks;
 //     td_sched0.ts_ftick = ticks;
 //     td_sched0.ts_slice = sched_slice;
 //
 //     fw_init();
+//
+////   printf("thread0: %p, tid: %d, name: %s\n", &thread0, thread0.td_tid, thread0.td_name);
+//
+//     fwd = fw_data_cpu(0);
+//     fwd->fw_current = &td_sched0.fw_task;
 //}
 //
 ///*
 //int
 //sched_rr_interval(void)
 //{
+//
 //     /* Convert sched_slice to hz */
 //     return (hz/(realstathz/sched_slice));
 //}
 // * Handle migration from sched_switch().  This happens only for
 // * cpu binding.
 // */
-////static struct mtx *
-////sched_switch_migrate(struct tdq *tdq, struct thread *td, int flags)
-////{
-////   struct tdq *tdn;
-////
-////   tdn = TDQ_CPU(td->td_sched->ts_cpu);
-////#ifdef SMP
-////   tdq_load_rem(tdq, td);
-////   /*
-////    * Do the lock dance required to avoid LOR.  We grab an extra
-////    * spinlock nesting to prevent preemption while we're
-////    * not holding either run-queue lock.
-////    */
-////   spinlock_enter();
-////   thread_lock_block(td);  /* This releases the lock on tdq. */
-////
-////   /*
-////    * Acquire both run-queue locks before placing the thread on the new
-////    * run-queue to avoid deadlocks created by placing a thread with a
-////    * blocked lock on the run-queue of a remote processor.  The deadlock
-////    * occurs when a third processor attempts to lock the two queues in
-////    * question while the target processor is spinning with its own
-////    * run-queue lock held while waiting for the blocked lock to clear.
-////    */
-////   tdq_lock_pair(tdn, tdq);
-////   tdq_add(tdn, td, flags);
-////   tdq_notify(tdn, td);
-////   TDQ_UNLOCK(tdn);
-////   spinlock_exit();
-////#endif
-////   return (TDQ_LOCKPTR(tdn));
-////}
+//static struct mtx *
+//sched_switch_migrate(struct tdq *tdq, struct thread *td, int flags)
+//{
+//     struct tdq *tdn;
+//
+//     tdn = TDQ_CPU(td->td_sched->ts_cpu);
+//#ifdef SMP
+//     tdq_load_rem(tdq, td);
+//     /*
+//      * Do the lock dance required to avoid LOR.  We grab an extra
+//      * spinlock nesting to prevent preemption while we're
+//      * not holding either run-queue lock.
+//      */
+//     spinlock_enter();
+//     thread_lock_block(td);  /* This releases the lock on tdq. */
+//
+//     /*
+//      * Acquire both run-queue locks before placing the thread on the new
+//      * run-queue to avoid deadlocks created by placing a thread with a
+//      * blocked lock on the run-queue of a remote processor.  The deadlock
+//      * occurs when a third processor attempts to lock the two queues in
+//      * question while the target processor is spinning with its own
+//      * run-queue lock held while waiting for the blocked lock to clear.
+//      */
+//     tdq_lock_pair(tdn, tdq);
+//     tdq_add(tdn, td, flags);
+//     tdq_notify(tdn, td);
+//     TDQ_UNLOCK(tdn);
+//     spinlock_exit();
+//#endif
+//     return (TDQ_LOCKPTR(tdn));
+//}
 //
 ///*
 // * Variadic version of thread_lock_unblock() that does not assume td_lock
 //sched_switch(struct thread *td, struct thread *newtd, int flags)
 //{
 //     struct tdq *tdq;
+//     struct td_sched *ts;
 //     struct mtx *mtx;
 //     int srqflag;
-//     struct fw_queues *q = cpu_queue(0);
+//     int cpuid;
 //
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     KASSERT(newtd == NULL, ("sched_switch: Unsupported newtd argument"));
 //
+//     cpuid = PCPU_GET(cpuid);
 //     tdq = TDQ_CPU(cpuid);
+//     ts = td->td_sched;
 //     mtx = td->td_lock;
 //
-//
+////   tdq_print(tdq);
+////   sched_pctcpu_update(ts, 1);
+//     ts->ts_rltick = ticks;
+//     td->td_lastcpu = td->td_oncpu;
+//     td->td_oncpu = NOCPU;
 //     if (!(flags & SW_PREEMPT))
 //             td->td_flags &= ~TDF_NEEDRESCHED;
 //     td->td_owepreempt = 0;
+//     tdq->tdq_switchcnt++;
+//
+//
+//
+////   /*
+////    * The lock pointer in an idle thread should never change.  Reset it
+////    * to CAN_RUN as well.
+////    */
+////   if (TD_IS_IDLETHREAD(td)) {
+////           MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
+////           TD_SET_CAN_RUN(td);
+////   } else if (TD_IS_RUNNING(td)) {
+////           MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
+////           srqflag = (flags & SW_PREEMPT) ?
+////               SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED :
+////               SRQ_OURSELF|SRQ_YIELDING;
+////#ifdef SMP
+////           if (THREAD_CAN_MIGRATE(td) && !THREAD_CAN_SCHED(td, ts->ts_cpu))
+////                   ts->ts_cpu = sched_pickcpu(td, 0);
+////#endif
+////           if (ts->ts_cpu == cpuid)
+////                   tdq_runq_add(tdq, td, srqflag);
+////           else {
+////                   KASSERT(THREAD_CAN_MIGRATE(td) ||
+////                       (ts->ts_flags & TSF_BOUND) != 0,
+////                       ("Thread %p shouldn't migrate", td));
+////                   mtx = sched_switch_migrate(tdq, td, srqflag);
+////           }
+////   }
+////// else if (TD_IS_EXITING(td)) {
+//////         fw_notify(FW_RELEASE, (void*)&td->td_sched->fw_task);
+////// }
+////   else {
+////           /* This thread must be going to sleep. */
+////           TDQ_LOCK(tdq);
+////           mtx = thread_lock_block(td);
+////           tdq_load_rem(tdq, td);
+////
+////           fw_notify(FW_EVENT_WAIT, (void*)&td->td_sched->fw_task);
+////   }
+//
 //
 //     /*
 //      * The lock pointer in an idle thread should never change.  Reset it
 //             TD_SET_CAN_RUN(td);
 //     }
 //     else if (TD_IS_RUNNING(td)) {
-//             td->td_sched->fw_task.real_task = td;
-//             fw_notify(FW_ADMIT, (void*)&td->td_sched->fw_task);
+//             srqflag = (flags & SW_PREEMPT) ?
+//                     SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED :
+//                     SRQ_OURSELF|SRQ_YIELDING;
+//#ifdef SMP
+//             if (THREAD_CAN_MIGRATE(td) && !THREAD_CAN_SCHED(td, ts->ts_cpu))
+//                     ts->ts_cpu = sched_pickcpu(td, 0);
+//#endif
+//             if (ts->ts_cpu == cpuid)
+//                     tdq_runq_add(tdq, td, srqflag);
+//             else {
+//                     KASSERT(THREAD_CAN_MIGRATE(td) ||
+//                             (ts->ts_flags & TSF_BOUND) != 0,
+//                             ("Thread %p shouldn't migrate", td));
+//                     mtx = sched_switch_migrate(tdq, td, srqflag);
+//             }
+////           fw_notify(FW_EVENT_OCCURS, (void*)&td->td_sched->fw_task);
 //     }
+////   else if (TD_IS_EXITING(td)) {
+////           fw_notify(FW_RELEASE, (void*)&td->td_sched->fw_task);
+////   }
 //     else {
-//             /* This thread must be going to sleep. */
+//             /* This thread must be going to sleep.
+//              *              TD_IS_SLEEPING(td)              2
+//              *              TD_AWAITING_INTR(td)    10
+//              * */
 //             TDQ_LOCK(tdq);
 //             mtx = thread_lock_block(td);
 //             tdq->tdq_load--;
+////           printf("\nsched_switch: inhibitors = %x state %x", td->td_inhibitors, td->td_state);
+//             fw_notify(FW_EVENT_WAIT, (void*)&td->td_sched->fw_task);
 //     }
 //
-//     newtd = sched_choose();
 //
-//     TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
-//     cpu_switch(td, newtd, mtx);
+//
+//
+//     /*
+//      * We enter here with the thread blocked and assigned to the
+//      * appropriate cpu run-queue or sleep-queue and with the current
+//      * thread-queue locked.
+//      */
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED | MA_NOTRECURSED);
+//     newtd = choosethread();
+//     /*
+//      * Call the MD code to switch contexts if necessary.
+//      */
+//     if (td != newtd) {
+//#ifdef       HWPMC_HOOKS
+//             if (PMC_PROC_IS_USING_PMCS(td->td_proc))
+//                     PMC_SWITCH_CONTEXT(td, PMC_FN_CSW_OUT);
+//#endif
+//             SDT_PROBE2(sched, , , off_cpu, td, td->td_proc);
+//             lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
+//             TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
+////           sched_pctcpu_update(newtd->td_sched, 0);
+//
+//#ifdef KDTRACE_HOOKS
+//             /*
+//              * If DTrace has set the active vtime enum to anything
+//              * other than INACTIVE (0), then it should have set the
+//              * function to call.
+//              */
+//             if (dtrace_vtime_active)
+//                     (*dtrace_vtime_switch_func)(newtd);
+//#endif
+//
+//             cpu_switch(td, newtd, mtx);
+//             /*
+//              * We may return from cpu_switch on a different cpu.  However,
+//              * we always return with td_lock pointing to the current cpu's
+//              * run queue lock.
+//              */
+//             cpuid = PCPU_GET(cpuid);
+//             tdq = TDQ_CPU(cpuid);
+//             lock_profile_obtain_lock_success(
+//                 &TDQ_LOCKPTR(tdq)->lock_object, 0, 0, __FILE__, __LINE__);
+//
+//             SDT_PROBE0(sched, , , on_cpu);
+//#ifdef       HWPMC_HOOKS
+//             if (PMC_PROC_IS_USING_PMCS(td->td_proc))
+//                     PMC_SWITCH_CONTEXT(td, PMC_FN_CSW_IN);
+//#endif
+//     } else {
+//             thread_unblock_switch(td, mtx);
+//             SDT_PROBE0(sched, , , remain_cpu);
+//     }
+//     /*
+//      * Assert that all went well and return.
+//      */
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED|MA_NOTRECURSED);
+//     MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
+//     td->td_oncpu = cpuid;
 //}
 //
 ///*
 // * Schedule a thread to resume execution and record how long it voluntarily
 // * slept.  We also update the pctcpu, interactivity, and priority.
 // */
-//void
-//sched_wakeup(struct thread *td)
+////void
+////sched_wakeup(struct thread *td)
+////{
+////   struct td_sched *ts;
+////// int slptick;
+////
+////   THREAD_LOCK_ASSERT(td, MA_OWNED);
+////   ts = td->td_sched;
+////   td->td_flags &= ~TDF_CANSWAP;
+////// /*
+//////  * If we slept for more than a tick update our interactivity and
+//////  * priority.
+//////  */
+////// slptick = td->td_slptick;
+////// td->td_slptick = 0;
+////// if (slptick && slptick != ticks) {
+//////         ts->ts_slptime += (ticks - slptick) << SCHED_TICK_SHIFT;
+//////         sched_interact_update(td);
+//////         sched_pctcpu_update(ts, 0);
+////// }
+////   /* Reset the slice value after we sleep. */
+////   ts->ts_slice = sched_slice;
+////   sched_add(td, SRQ_BORING);
+////}
+//
+//void sched_wakeup(struct thread *td)
 //{
 //     struct td_sched *ts;
+//     struct tdq *tdq;
+//     struct thread *ctd;
+//     int cpri;
+//     int pri;
+//     int flags = SRQ_BORING;
+//#ifdef SMP
+//     int cpu;
+//#endif
+//
 //
 //     THREAD_LOCK_ASSERT(td, MA_OWNED);
 //     ts = td->td_sched;
 //     /* Reset the slice value after we sleep. */
 //     ts->ts_slice = sched_slice;
 //
+//     tdq = TDQ_SELF();
+//     TDQ_LOCK(tdq);
+//
+//     thread_lock_set(td, TDQ_LOCKPTR(tdq));
+//
+//     fw_notify(FW_EVENT_OCCURS, (void*)&td->td_sched->fw_task);
+//
+////   tdq->tdq_load++;
+//
+////   if (!(flags & SRQ_YIELDING)) {
+////           ctd = curthread;
+////           pri = td->td_priority;
+////           cpri = ctd->td_priority;
+////           if (!sched_shouldpreempt(pri, cpri, 0))
+////                   return;
+////           ctd->td_owepreempt = 1;
+////   }
 //
-//     sched_add(td, SRQ_BORING);
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//             /*
+//              * Recalculate the priority before we select the target cpu or
+//              * run-queue.
+//              */
+//     //      if (PRI_BASE(td->td_pri_class) == PRI_TIMESHARE)
+//     //              sched_priority(td);
+//     #ifdef SMP
+//             /*
+//              * Pick the destination cpu and if it isn't ours transfer to the
+//              * target cpu.
+//              */
+//             cpu = sched_pickcpu(td, flags);
+//             tdq = sched_setcpu(td, cpu, flags);
+//             tdq_add(tdq, td, flags);
+//             if (cpu != PCPU_GET(cpuid)) {
+//                     tdq_notify(tdq, td);
+//                     return;
+//             }
+//     #else
+//             tdq = TDQ_SELF();
+//             TDQ_LOCK(tdq);
+//             /*
+//              * Now that the thread is moving to the run-queue, set the lock
+//              * to the scheduler's lock.
+//              */
+//             thread_lock_set(td, TDQ_LOCKPTR(tdq));
+//             tdq_add(tdq, td, flags);
+//     #endif
+//             if (!(flags & SRQ_YIELDING))
+//                     sched_setpreempt(td);
 //}
 //
 ///*
 //     ts2->ts_slptime = ts->ts_slptime;
 //     ts2->ts_runtime = ts->ts_runtime;
 //     ts2->ts_slice = 1;      /* Attempt to quickly learn interactivity. */
+//
+//     ts2->fw_task.real_task = child;
+//
 //#ifdef KTR
 //     bzero(ts2->ts_name, sizeof(ts2->ts_name));
 //#endif
 //void
 //sched_class(struct thread *td, int class)
 //{
-//     struct fw_queues *q;
+//     struct fw_data *fwd;
 //     struct fw_task *p = &td->td_sched->fw_task;
 //     int i;
 //
+//
 //     THREAD_LOCK_ASSERT(td, MA_OWNED);
 //
-//     if (class == PRI_IDLE) {
+//     if (TD_IS_IDLETHREAD(td)) {
+//             printf("idle name = %s\n", td->td_name);
 //             FW_FOREACH_CPU(i) {
-//                     q = cpu_queue(i);
-//                     q->fw_idle = p;
+//                     fwd = fw_data_cpu(i);
+//                     fwd->fw_idle = p;
 //                     p->real_task = td;
 //             }
 //     }
 //
 //     if (td->td_pri_class == class)
 //             return;
-//
 //     td->td_pri_class = class;
 //}
 //
 //struct thread *
 //sched_choose(void)
 //{
-//     struct thread *newtd;
-//     struct fw_queues *q = cpu_queue(0);
+//     struct thread *td;
+//     struct tdq *tdq;
 //
 //
 //     fw_notify(FW_DISPATCH, NULL);
 //
-//     newtd = (struct thread*)q->fw_current->real_task;
-//     TD_SET_RUNNING(newtd);
+////   printf("sched_choose: next task oder whateva %p\n", (struct thread*)fwi->fw_current->real_task);
+//
+//     tdq = TDQ_SELF();
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//
+//     td = tdq_choose(tdq);
+//     if (td) {
+//             tdq_runq_rem(tdq, td);
+////           tdq->tdq_lowpri = td->td_priority;
+//             return (td);
+//     }
+////   tdq->tdq_lowpri = PRI_MAX_IDLE;
+//     return (PCPU_GET(idlethread));
 //}
 //
 ///*
 // * Set owepreempt if necessary.  Preemption never happens directly in ULE,
 // * we always request it once we exit a critical section.
 // */
-//static inline void
+//void
 //sched_setpreempt(struct thread *td)
 //{
 //     struct thread *ctd;
 //tdq_add(struct tdq *tdq, struct thread *td, int flags)
 //{
 //
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   KASSERT((td->td_inhibitors == 0),
-////       ("sched_add: trying to run inhibited thread"));
-////   KASSERT((TD_CAN_RUN(td) || TD_IS_RUNNING(td)),
-////       ("sched_add: bad thread state"));
-////   KASSERT(td->td_flags & TDF_INMEM,
-////       ("sched_add: thread swapped out"));
-////
-////// if (td->td_priority < tdq->tdq_lowpri)
-//////         tdq->tdq_lowpri = td->td_priority;
-////// tdq_runq_add(tdq, td, flags);
-////
-////   td->td_sched->fw_task.real_task = td;
-////   fw_notify(FW_ADMIT, (void*)&td->td_sched->fw_task);
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     KASSERT((td->td_inhibitors == 0),
+//         ("sched_add: trying to run inhibited thread"));
+//     KASSERT((TD_CAN_RUN(td) || TD_IS_RUNNING(td)),
+//         ("sched_add: bad thread state"));
+//     KASSERT(td->td_flags & TDF_INMEM,
+//         ("sched_add: thread swapped out"));
+//
+////   if (td->td_priority < tdq->tdq_lowpri)
+////           tdq->tdq_lowpri = td->td_priority;
+//     tdq_runq_add(tdq, td, flags);
+//     tdq_load_add(tdq, td);
 //}
 //
 ///*
 //sched_add(struct thread *td, int flags)
 //{
 //     struct tdq *tdq;
+//#ifdef SMP
+//     int cpu;
+//#endif
+//     struct fw_task *fwt;
+//
 //
+//     fwt = &td->td_sched->fw_task;
 //
+////   KTR_STATE2(KTR_SCHED, "thread", sched_tdname(td), "runq add",
+////       "prio:%d", td->td_priority, KTR_ATTR_LINKED,
+////       sched_tdname(curthread));
+////   KTR_POINT1(KTR_SCHED, "thread", sched_tdname(curthread), "wokeup",
+////       KTR_ATTR_LINKED, sched_tdname(td));
+////   SDT_PROBE4(sched, , , enqueue, td, td->td_proc, NULL,
+////       flags & SRQ_PREEMPTED);
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     /*
+//      * Recalculate the priority before we select the target cpu or
+//      * run-queue.
+//      */
+////   if (PRI_BASE(td->td_pri_class) == PRI_TIMESHARE)
+////           sched_priority(td);
+//#ifdef SMP
+//     /*
+//      * Pick the destination cpu and if it isn't ours transfer to the
+//      * target cpu.
+//      */
+//     cpu = sched_pickcpu(td, flags);
+//     tdq = sched_setcpu(td, cpu, flags);
+//     tdq_add(tdq, td, flags);
+//     if (cpu != PCPU_GET(cpuid)) {
+//             tdq_notify(tdq, td);
+//             return;
+//     }
+//#else
 //     tdq = TDQ_SELF();
 //     TDQ_LOCK(tdq);
-//
+//     /*
+//      * Now that the thread is moving to the run-queue, set the lock
+//      * to the scheduler's lock.
+//      */
 //     thread_lock_set(td, TDQ_LOCKPTR(tdq));
-//
-//     td->td_sched->fw_task.real_task = td;
-//     fw_notify(FW_ADMIT, (void*)&td->td_sched->fw_task);
-//
-//     tdq->tdq_load++;
-//
+//     tdq_add(tdq, td, flags);
+//#endif
 //     if (!(flags & SRQ_YIELDING))
 //             sched_setpreempt(td);
+//
+////   tdq_print(1);
+////   fw_printf("sched_add: addr %p name %s(%d)\n", (void*)td, td->td_name, td->td_tid);
+////   fwt->cpu = cpu;
+//
+//     if (fwt->state & FW_BLOCKED) {
+//             fw_notify(FW_EVENT_OCCURS, (void*)fwt);
+//     }
+//     else {
+//             fw_notify(FW_ADMIT, (void*)fwt);
+//     }
 //}
 //
 ///*
 //{
 //     struct tdq *tdq;
 //
+//     KTR_STATE1(KTR_SCHED, "thread", sched_tdname(td), "runq rem",
+//         "prio:%d", td->td_priority);
+//     SDT_PROBE3(sched, , , dequeue, td, td->td_proc, NULL);
 //     tdq = TDQ_CPU(td->td_sched->ts_cpu);
-//     tdq->tdq_load--;
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
+//     KASSERT(TD_ON_RUNQ(td),
+//         ("sched_rem: thread not on run queue"));
+//     tdq_runq_rem(tdq, td);
+//     tdq_load_rem(tdq, td);
 //     TD_SET_CAN_RUN(td);
+////   if (td->td_priority == tdq->tdq_lowpri)
+////           tdq_setlowpri(tdq, NULL);
 //}
 //
 ///*
 //fixpt_t
 //sched_pctcpu(struct thread *td)
 //{
-////   fixpt_t pctcpu;
-////   struct td_sched *ts;
-////
-////   pctcpu = 0;
-////   ts = td->td_sched;
-////   if (ts == NULL)
-////           return (0);
-////
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     fixpt_t pctcpu;
+//     struct td_sched *ts;
+//
+//     pctcpu = 0;
+//     ts = td->td_sched;
+//     if (ts == NULL)
+//             return (0);
+//
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
 ////   sched_pctcpu_update(ts, TD_IS_RUNNING(td));
 ////   if (ts->ts_ticks) {
 ////           int rtick;
 ////           rtick = min(SCHED_TICK_HZ(ts) / SCHED_TICK_SECS, hz);
 ////           pctcpu = (FSCALE * ((FSCALE * rtick)/hz)) >> FSHIFT;
 ////   }
-////
-////   return (pctcpu);
+//
+//     return (pctcpu);
 //}
 //
 ///*
 //int
 //sched_load(void)
 //{
-////#ifdef SMP
-////   int total;
-////   int i;
-////
-////   total = 0;
-////   CPU_FOREACH(i)
-////           total += TDQ_CPU(i)->tdq_sysload;
-////   return (total);
-////#else
-////   return (TDQ_SELF()->tdq_sysload);
-////#endif
+//#ifdef SMP
+//     int total;
+//     int i;
+//
+//     total = 0;
+//     CPU_FOREACH(i)
+//             total += TDQ_CPU(i)->tdq_sysload;
+//     return (total);
+//#else
+//     return (TDQ_SELF()->tdq_sysload);
+//#endif
 //}
 //
 //int
 //     mtx_assert(&Giant, MA_NOTOWNED);
 //     td = curthread;
 //     tdq = TDQ_SELF();
-//     printf("SCHED_IDLETD\n");
 //     for (;;) {
 //#ifdef SMP
 //             if (tdq_idled(tdq) == 0) {
 //             }
 //#endif
 //             switchcnt = tdq->tdq_switchcnt + tdq->tdq_oldswitchcnt;
+////           tdq_print(TDQ_ID(tdq));
 //             /*
 //              * If we're switching very frequently, spin while checking
 //              * for load rather than entering a low power state that
 //     struct tdq *tdq;
 //
 //     tdq = TDQ_SELF();
-//
 //     if (td == NULL) {
 //             /* Correct spinlock nesting and acquire the correct lock. */
 //             TDQ_LOCK(tdq);
 //             PCPU_SET(switchticks, ticks);
 //     } else {
 //             MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
-//             tdq->tdq_load--;
+//             tdq_load_rem(tdq, td);
 //             lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
 //     }
+//     KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
+//     fw_notify(FW_RELEASE, (void*)&td->td_sched->fw_task);
+//     newtd = choosethread();
 //
-//     newtd = sched_choose();
 //
 //     TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
 //     cpu_throw(td, newtd);           /* doesn't return */
 //}
 //
+//
+////void sched_throw(struct thread *td)
+////{
+////   struct tdq *tdq;
+////
+////
+////   tdq = TDQ_SELF();
+////
+////   if (td == NULL) {
+////           /* Correct spinlock nesting and acquire the correct lock. */
+////           TDQ_LOCK(tdq);
+////           spinlock_exit();
+////           PCPU_SET(switchtime, cpu_ticks());
+////           PCPU_SET(switchticks, ticks);
+////   } else {
+//////         MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
+////           tdq->tdq_load--;
+////           lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
+////   }
+////
+////
+////   sched_switch(td, NULL, 0);
+////}
+//
 ///*
 // * This is called from fork_exit().  Just acquire the correct locks and
 // * let fork do the rest of the work.
 //void
 //sched_fork_exit(struct thread *td)
 //{
+//     struct td_sched *ts;
 //     struct tdq *tdq;
+//     int cpuid;
 //
+//     /*
+//      * Finish setting up thread glue so that it begins execution in a
+//      * non-nested critical section with the scheduler lock held.
+//      */
+//     cpuid = PCPU_GET(cpuid);
 //     tdq = TDQ_CPU(cpuid);
-//
+//     ts = td->td_sched;
 //     if (TD_IS_IDLETHREAD(td))
 //             td->td_lock = TDQ_LOCKPTR(tdq);
+//     MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
+//     td->td_oncpu = cpuid;
+//     TDQ_LOCK_ASSERT(tdq, MA_OWNED | MA_NOTRECURSED);
+//     lock_profile_obtain_lock_success(
+//         &TDQ_LOCKPTR(tdq)->lock_object, 0, 0, __FILE__, __LINE__);
 //}
 //
 ///*
 ///* ps compat.  All cpu percentages from ULE are weighted. */
 //static int ccpu = 0;
 //SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, "");
-//