Fixed broken sched_ule.c
authorJens Krieg <jkrieg@mailbox.tu-berlin.de>
Fri, 13 Dec 2013 10:05:24 +0000 (11:05 +0100)
committerJens Krieg <jkrieg@mailbox.tu-berlin.de>
Fri, 13 Dec 2013 10:05:24 +0000 (11:05 +0100)
29 files changed:
sys/framework/Makefile [deleted file]
sys/framework/include/fw.h [deleted file]
sys/framework/include/fw_comm.h [deleted file]
sys/framework/include/fw_list.h [deleted file]
sys/framework/include/fw_modules.h [deleted file]
sys/framework/include/fw_task.h [deleted file]
sys/framework/include/fw_types.h [deleted file]
sys/framework/include/os.h [deleted file]
sys/framework/include/os_kdb.h [deleted file]
sys/framework/include/os_lock.h [deleted file]
sys/framework/include/os_sched.h [deleted file]
sys/framework/lib/fw.c [deleted file]
sys/framework/lib/fw_comm.c [deleted file]
sys/framework/lib/fw_list.c [deleted file]
sys/framework/lib/fw_modules.c [deleted file]
sys/framework/modules/round_robin.c [deleted file]
sys/framework/os/bertos/os.c [deleted file]
sys/framework/os/bertos/os.h [deleted file]
sys/framework/os/bertos/os_p.c [deleted file]
sys/framework/os/bertos/rules.mk [deleted file]
sys/framework/os/freebsd/fbsd_sched.c [deleted file]
sys/framework/os/freebsd/os.c [deleted file]
sys/framework/os/freebsd/os_kdb.c [deleted file]
sys/framework/os/freebsd/os_lock.c [deleted file]
sys/framework/os/freebsd/os_sched.c [deleted file]
sys/framework/os/linux/Makefile [deleted file]
sys/framework/os/linux/linux_sched.c [deleted file]
sys/framework/os/linux/os.c [deleted file]
sys/kern/sched_ule.c

diff --git a/sys/framework/Makefile b/sys/framework/Makefile
deleted file mode 100644 (file)
index b3e08db..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-MOD_SCHED_DIR?=$(PWD)
-OBJ= $(MOD_SCHED_DIR)/modules/rr_module.o 
-OBJ += $(MOD_SCHED_DIR)/fw_list.o $(MOD_SCHED_DIR)/fw.o $(MOD_SCHED_DIR)/fw_comm.o $(MOD_SCHED_DIR)/fw_modules.o
-LINUX_DIR?=$(PWD)/../
-
-ifeq ($(OS),linux)
-$(info ===COMPILING FOR LINUX===)
-include $(MOD_SCHED_DIR)/os/linux/Makefile
-else ifeq ($(OS),freebsd)
-else
-$(info ===COMPILING FOR SIMULATED OS===)
-include $(MOD_SCHED_DIR)/os/simulated/Makefile
-endif
-
-#kernel/sched.new/mod_sched.o: mod_sched_build
-
-
-all: mod_sched_build
-
-linux:
-       cd $(LINUX_DIR); \
-       rm -f $(LINUX_DIR)/build/kernel/sched.new/mod_sched.o; \
-       make V=1 O=$(LINUX_DIR)/build/ -j1 all
diff --git a/sys/framework/include/fw.h b/sys/framework/include/fw.h
deleted file mode 100644 (file)
index 2f75d24..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef FW_H_
-#define FW_H_
-
-#include "fw_types.h"
-#include "fw_task.h"
-#include "os.h"
-
-
-#define fw_printf              os_printf               /* Normalized OS independent version of printf */
-
-
-
-/**
- * \brief A printf function.
- *
- * @param formatstring The format string to print on screen.
- */
-//#define fw_printf(fmt, ...)  os_printf(fmt ,## __VA_ARGS__)
-
-/**
- * \brief Dynamic allocation of memory.
- *
- * @param size The amount of memory to allocate.
- * @return A pointer to the allocated memory.
- */
-void *fw_malloc(fw_size_t size);
-
-/**
- * \brief Releases a dynamically allocated chunk of memory.
- *
- * @param ptr Memory region to release.
- */
-void fw_free(void* ptr);
-
-/**
- * \brief Runs the given task on a (random) processing unit.
- *
- * @param task The task that shall run.
- */
-void fw_dispatch(fw_task_t *task);
-
-/**
- * \brief Runs the given task on the given processing unit.
- *
- * @param task The task that shall run.
- * @param cpu The CPU that will run the task.
- */
-void fw_dispatch_mp(fw_task_t *task, int cpu);
-
-/**
- * \brief Retrieves the currently running thread on the requested CPU.
- *
- * @param cpu The CPU of interest.
- * @return The thread structure of the requested or current CPU respectively.
- */
-fw_task_t *fw_current_task(int cpu);
-
-int fw_task_info(fw_task_t *task, char *buf, int length);
-
-int fw_register_module(void);
-
-void fw_init(void);
-
-#endif /* FW_H_ */
diff --git a/sys/framework/include/fw_comm.h b/sys/framework/include/fw_comm.h
deleted file mode 100644 (file)
index d8f4ba2..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef FW_COMM_H_
-#define FW_COMM_H_
-
-/**
- * Prototypes:
- *
- * SCHEDULE:   void (void);
- * ADMIT:              void (fw_task_t *task);
- * RELEASE:            void (fw_task_t *task);
- * EVENT:              void (fw_task_t *task);
- * EVENT_WAIT: void (fw_task_t *task);
- * SUSPEND:            void (fw_task_t *task);
- * ACTIVATE:   void (fw_task_t *task);
- *
- */
-typedef enum {FW_FIRST, SCHEDULE, ADMIT, RELEASE, EVENT, EVENT_WAIT, SUSPEND, ACTIVATE, FW_LAST} topic_t;
-
-void fw_subscribe(topic_t topic, void *callback);
-
-void fw_notify(topic_t topic, void *data);
-
-void fw_init_comm(void);
-
-#endif /* FW_COMM_H_ */
diff --git a/sys/framework/include/fw_list.h b/sys/framework/include/fw_list.h
deleted file mode 100644 (file)
index 3534f18..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _FW_LIST_H
-#define _FW_LIST_H
-
-
-/*
- * Copied and heavily modified from Linux implementation.
- *  Created on:23.07.2013
- *     Authors: Christian RenĂ© Sechting, Daniel Roehrig
- *
- */
-
-#undef offsetof
-#define offsetof(TYPE, MEMBER) ((fw_size_t) &((TYPE *)0)->MEMBER)
-
-/**
- * fw_container_of - cast a member of a structure out to the containing structure
- * @ptr:        the pointer to the member.
- * @type:       the type of the container struct this is embedded in.
- * @member:     the name of the member within the struct.
- *
- */
-#define fw_container_of(ptr, type, member) ({               \
-       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-       (type *)( (char *)__mptr - offsetof(type,member) );})
-
-
-typedef struct fw_list_head {
-       struct fw_list_head *next, *prev;
-} fw_list_head_t;
-
-/**
- * Initializing the list
- * @name: the head for your list.
- */
-#define FW_LIST_INIT(name)     name.next = name.prev = &(name)
-
-#define FW_LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define FW_LIST_HEAD(name) \
-       struct fw_list_head name = FW_LIST_HEAD_INIT(name)
-
-
-/**
- * fw_list_entry - get the struct for this entry
- * @ptr:       the &struct list_head pointer.
- * @type:      the type of the struct this is embedded in.
- * @member:    the name of the list_struct within the struct.
- */
-#define fw_list_entry(ptr, type, member) \
-       fw_container_of(ptr, type, member)
-
-/**
- * list_for_each_entry -       iterate over list of given type
- * @pos:       the type * to use as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- */
-#define fw_list_for_each_entry(pos, head, member)                              \
-       for (pos = fw_list_entry((head)->next, typeof(*pos), member);   \
-            &pos->member != (head);    \
-            pos = fw_list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-int fw_list_empty(const struct fw_list_head *head);
-
-/**
- * fw_list_length - returns the number of entries in a list.
- * @head: the &struct fw_list_head pointer.
- */
-int fw_list_length(const struct fw_list_head *head);
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-void __fw_list_add(struct fw_list_head *_new,
-                             struct fw_list_head *prev,
-                             struct fw_list_head *next);
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-void fw_list_add_tail(struct fw_list_head *_new, struct fw_list_head *head);
-
-/**
- * fw_list_add_first - add a new entry at the beginning of the list
- * @new: new entry to be added
- * @head: list head to add it after
- */
-void fw_list_add_first(struct fw_list_head *_new, struct fw_list_head *head);
-
-/**
- * fw_list_add_at_pos - add a new entry at this position (starting with 0);
- * @new: new entry to be added
- * @head: list head to add it after
- * @pos: position where to insert the element at
- */
-void fw_list_add_at_pos(struct fw_list_head *_new, struct fw_list_head *head, int pos);
-
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-void __fw_list_del(struct fw_list_head * prev, struct fw_list_head * next);
-
-void __fw_list_del_entry(struct fw_list_head *entry);
-
-/**
- * fw_list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-void fw_list_del(struct fw_list_head *entry);
-
-/*
- * pop functionality to remove the first element of the list an return it
- */
-struct fw_list_head *__fw_list_pop(struct fw_list_head *head);
-
-/*
- * use the define here to pop of the list to get the entry and not only the list element
- */
-#define fw_list_pop(head,type,member) fw_list_entry(__fw_list_pop(head),type,member)
-
-#endif
diff --git a/sys/framework/include/fw_modules.h b/sys/framework/include/fw_modules.h
deleted file mode 100644 (file)
index 11d5ff6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef FW_MODULES_H_
-#define FW_MODULES_H_
-
-#define FW_MAX_MODULES 8
-
-
-void fw_modules_init(void);
-
-int init_sched_rr_module(void);
-
-#endif /* FW_MODULES_H_ */
diff --git a/sys/framework/include/fw_task.h b/sys/framework/include/fw_task.h
deleted file mode 100644 (file)
index 9eb6c63..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * fw_task.h
- *
- * Framework Tasks (implemented in the os spcific folder)
- *
- *  Created on: 05.11.2013
- *      Author: Daniel Roehrig, Christian Rene Sechting
- */
-#ifndef FW_TASK_H_
-#define FW_TASK_H_
-
-#include "fw_list.h"
-#include "fw_modules.h"
-
-#define task_context_t void
-
-typedef enum {RUNNING, BLOCKED, READY} fw_task_state_t;
-
-typedef struct fw_task{
-       task_context_t *task_context;
-       void *real_task;
-
-       fw_task_state_t state;
-
-       void *module_data[FW_MAX_MODULES];
-
-       fw_list_head_t list;
-} fw_task_t;
-
-typedef struct fw_task_list_entry{
-       fw_list_head_t list;
-       fw_task_t task;
-       void *module_data[FW_MAX_MODULES];
-} fw_task_list_entry_t;
-
-/*
- *  initialize the task_struct_padding with 0 and
- *  creates a list for all tasks
- */
-void init_fw_tasks(void);
-
-/*
- *  TODO: check if needed
- *  every scheduler module can demand individual
- *  fields in the task_struct and this is the
- *  overall counter of all extra memory that needs
- *  to be allocated from the framework per task
- */
-extern unsigned long task_struct_padding;
-
-/*
- * returns the fw_task equivalent of the given os task
- */
-struct fw_task *find_fw_task(void *real_task);
-
-/*
- *  returns the os task equivalent of the given fw_task
- */
-void *find_real_task(struct fw_task *task);
-
-/*
- *  creates a fw_task equivalent for the given os task
- *  or returns the fw_task if already there.
- */
-struct fw_task *register_task(void *real_task);
-
-int fw_task_is_registered(void *tsk);
-void insert_fw_task(struct fw_task *new_task, void *tsk);
-
-void set_idle_task(struct fw_task *idle);
-struct fw_task *get_idle_task(void);
-
-int fw_get_state(struct fw_task *task);
-int fw_get_pid(struct fw_task *task);
-
-#endif /* FW_TASK_H_ */
diff --git a/sys/framework/include/fw_types.h b/sys/framework/include/fw_types.h
deleted file mode 100644 (file)
index 92e3ad9..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * types.h
- *
- *  Created on: 23.10.2013
- *      Author: Anselm Busse
- */
-
-#ifndef FW_TYPES_H_
-#define FW_TYPES_H_
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
-#define fw_spinlock_t int
-#define FW_SPINLOCK_CREATE(name) fw_spinlock_t name = 0
-
-//int for 8 bit long for 64 bit?
-#define fw_size_t long
-
-#endif /* FW_TYPES_H_ */
diff --git a/sys/framework/include/os.h b/sys/framework/include/os.h
deleted file mode 100644 (file)
index 9dafe72..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * \file os.h
- * \brief Function prototypes for operating system depend code.
- * \author Anselm Busse
- *
- * This file defines functions that have to be implemented explicitly for every operating system
- */
-
-#ifndef OS_H_
-#define OS_H_
-
-#include "fw_types.h"
-#include "fw_task.h"
-
-
-#define os_printf              printf                  /* Mapping of OS dependent printf */
-
-
-/**
- * \brief Dynamic allocation of memory.
- *
- * @param size The amount of memory to allocate.
- * @return A pointer to the allocated memory.
- */
-void *os_malloc(fw_size_t size);
-
-/**
- * \brief Releases a dynamically allocated chunk of memory.
- *
- * @param ptr Memory region to release.
- */
-void os_free(void* ptr);
-
-/**
- * \brief Initialization of the operating depended code.
- *
- * @return Should return 0 iff initialization successful.
- */
-int os_init_os(void);
-
-/*
-#if 1
-#include "bertos/os.h"
-#endif
-*/
-
-#endif /* OS_H_ */
diff --git a/sys/framework/include/os_kdb.h b/sys/framework/include/os_kdb.h
deleted file mode 100644 (file)
index b80e532..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * os_kdb.h
- *
- *  Created on: 10.12.2013
- *      Author: jkrieg
- */
-
-#ifndef OS_KDB_H_
-#define OS_KDB_H_
-
-#include "fw_types.h"
-#include "fw_task.h"
-
-
-
-int os_task_name(fw_task_t *task, char *buf, fw_size_t size);
-
-const char *os_task_info(fw_task_t *task);
-
-#endif /* OS_KDB_H_ */
diff --git a/sys/framework/include/os_lock.h b/sys/framework/include/os_lock.h
deleted file mode 100644 (file)
index 50a8b1a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * os_lock.h
- *
- *  Created on: 10.12.2013
- *      Author: jkrieg
- */
-
-#ifndef OS_LOCK_H_
-#define OS_LOCK_H_
-
-#include "fw_types.h"
-#include "fw_task.h"
-
-
-
-void os_spinlock(fw_spinlock_t *lock);
-
-void os_spinunlock(fw_spinlock_t *lock);
-
-
-#endif /* OS_LOCK_H_ */
diff --git a/sys/framework/include/os_sched.h b/sys/framework/include/os_sched.h
deleted file mode 100644 (file)
index 54a9e1f..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * sched.h
- *
- *  Created on: 10.12.2013
- *      Author: jkrieg
- */
-
-#ifndef SCHED_H_
-#define SCHED_H_
-
-#include "fw_types.h"
-#include "fw_task.h"
-
-
-/**
- * \brief Runs the given task on a (random) processing unit.
- *
- * @param task The task that shall run.
- */
-void os_dispatch(fw_task_t *task);
-
-/**
- * \brief Runs the given task on the given processing unit.
- *
- * @param task The task that shall run.
- * @param cpu The CPU that will run the task.
- */
-void os_dispatch_mp(fw_task_t *task, int cpu);
-
-/**
- * \brief      Returns a fw_task pointer from the given CPU.
- *
- * @param      task    Existing CPU.
- * @return     Pointer of the running task.
- */
-fw_task_t *os_current_task(int cpu);
-
-#endif /* SCHED_H_ */
diff --git a/sys/framework/lib/fw.c b/sys/framework/lib/fw.c
deleted file mode 100644 (file)
index 2e38421..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * fw.c
- *
- * Framework functionality is mapped to os functions.
- *
- *      Author: Daniel Roehrig, Christian Rene Sechting
- */
-
-#include "fw.h"
-#include "fw_comm.h"
-#include "os.h"
-#include "os_lock.h"
-#include "os_kdb.h"
-#include "os_sched.h"
-
-
-
-void *fw_malloc(fw_size_t size)
-{
-       return os_malloc(size);
-}
-
-void fw_free(void* ptr)
-{
-       os_free(ptr);
-}
-
-void fw_dispatch(fw_task_t *task)
-{
-       os_dispatch(task);
-}
-
-void fw_dispatch_mp(fw_task_t *task, int cpu)
-{
-       os_dispatch_mp(task, cpu);
-}
-
-fw_task_t *fw_current_task(int cpu)
-{
-       return os_current_task(cpu);
-}
-
-int fw_task_info(fw_task_t *task, char *buf, int length)
-{
-       int count = 0;
-
-//     count += snprintf(buf, length, "Name: ");
-//
-//     count += os_task_name(task, buf+count, length-count);
-//
-//     count += snprintf(buf+count, length-count, ", State: ");
-//
-//
-//     switch(task->state) {
-//     case RUNNING:
-//             count += snprintf(buf+count, length-count, "running");
-//             break;
-//     case BLOCKED:
-//             count += snprintf(buf+count, length-count, "blocked");
-//             break;
-//     case READY:
-//             count += snprintf(buf+count, length-count, "ready");
-//             break;
-//     default:
-//             count += snprintf(buf+count, length-count, "unknown");
-//             break;
-//     }
-
-       return count;
-}
-
-int fw_module_count;
-int fw_register_module(){
-       return (fw_module_count+1) == FW_MAX_MODULES ? -1 : fw_module_count++;
-}
-
-void fw_init()
-{
-       fw_module_count = 0;
-
-       os_init_os();
-       fw_init_comm();
-       fw_modules_init();
-}
diff --git a/sys/framework/lib/fw_comm.c b/sys/framework/lib/fw_comm.c
deleted file mode 100644 (file)
index 7d885ec..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * fw_comm.c
- *
- * Simplistic Pub-Sub-System
- *
- *             Author: Anselm Busse, Daniel Roehrig, Christian Rene Sechting
- */
-
-#include "fw_comm.h"
-#include "fw_list.h"
-#include "fw.h"
-
-fw_list_head_t topics[FW_LAST-FW_FIRST];
-
-struct fw_topic_element {
-       fw_list_head_t list;
-       void *callback;
-};
-
-
-void fw_subscribe(topic_t topic, void *callback)
-{
-       struct fw_topic_element *subscriber = fw_malloc(sizeof(struct fw_topic_element));
-
-       subscriber->callback = callback;
-       fw_list_add_tail(&subscriber->list, &topics[topic]);
-}
-
-void fw_notify(topic_t topic, void *data)
-{
-       struct fw_topic_element *iter;
-
-       fw_list_for_each_entry(iter, &topics[topic], list)
-               ((void (*)(void *))iter->callback)(data);
-}
-
-void fw_init_comm()
-{
-       int i;
-
-       for(i=FW_FIRST; i<FW_LAST; i++){
-               FW_LIST_INIT(topics[i]);
-       }
-}
diff --git a/sys/framework/lib/fw_list.c b/sys/framework/lib/fw_list.c
deleted file mode 100644 (file)
index 8621115..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#include <fw_list.h>
-#include <fw_types.h>
-
-/*
- *     ALL LIST FUNCTIONALITIES
- */
-
-int fw_list_empty(const fw_list_head_t *head)
-{
-       return (head->next == (fw_list_head_t*)head);
-}
-
-int fw_list_length(const fw_list_head_t *head)
-{
-       int length = 0;
-       fw_list_head_t* start;
-
-       if (fw_list_empty(head)) {
-               return 0;
-       }
-       start = head->next;
-
-       while (start != head) {
-               start = start->next;
-               length++;
-       }
-
-       return length;
-}
-
-void __fw_list_add(fw_list_head_t *_new,
-                             fw_list_head_t *prev,
-                             fw_list_head_t *next)
-{
-       next->prev = _new;
-       _new->next = next;
-       _new->prev = prev;
-       prev->next = _new;
-}
-
-void fw_list_add_tail(fw_list_head_t *_new, fw_list_head_t *head)
-{
-       __fw_list_add(_new, head->prev, head);
-}
-
-void fw_list_add_first(fw_list_head_t *_new, fw_list_head_t *head)
-{
-       __fw_list_add(_new, head, head->next);
-}
-
-void fw_list_add_at_pos(fw_list_head_t *_new, fw_list_head_t *head, int pos)
-{
-       if ((pos <= fw_list_length(head)) && (pos >= 0)) {
-               while (pos-- > 0) {
-                       head = head->next;
-               }
-               __fw_list_add(_new, head, head->next);
-       }
-       else{
-               // TODO: was is wenn pos >fw_list_length ist? hinten einfuegen?
-               fw_list_add_tail(_new, head);
-       }
-}
-
-void __fw_list_del(fw_list_head_t * prev, fw_list_head_t * next)
-{
-       next->prev = prev;
-       prev->next = next;
-}
-
-void __fw_list_del_entry(fw_list_head_t *entry)
-{
-       __fw_list_del(entry->prev, entry->next);
-}
-
-#define LIST_POISON1  ((void *) 0x00100100)
-#define LIST_POISON2  ((void *) 0x00200200)
-
-void fw_list_del(fw_list_head_t *entry)
-{
-       if (entry->next!=LIST_POISON1 && entry->prev!=LIST_POISON2)
-       {
-               __fw_list_del(entry->prev, entry->next);
-               entry->next = LIST_POISON1;
-               entry->prev = LIST_POISON2;
-       }
-}
-
-fw_list_head_t *__fw_list_pop(fw_list_head_t *head)
-{
-       fw_list_head_t *ret = head->next;
-       if (fw_list_empty(head)){
-               return NULL;
-       }
-
-       fw_list_del(ret);
-
-       return ret;
-}
diff --git a/sys/framework/lib/fw_modules.c b/sys/framework/lib/fw_modules.c
deleted file mode 100644 (file)
index c9771a1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * fw_modules.c
- *
- *
- */
-#include "fw_modules.h"
-
-
-
-void fw_modules_init(void)
-{
-       rr_init();
-//     init_sched_rr_module();
-}
diff --git a/sys/framework/modules/round_robin.c b/sys/framework/modules/round_robin.c
deleted file mode 100644 (file)
index a4d208f..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-
-#include <fw.h>
-#include <fw_comm.h>
-#include "fw_modules.h"
-//#include <kern/proc.h>
-//#include <cpu/irq.h>
-
-void rr_print_ready_list(void);
-void rr_schedule(void);
-void rr_task_admit(fw_task_t *task);
-void rr_task_release(fw_task_t *task);
-void rr_task_wait(fw_task_t *task);
-void rr_task_event(fw_task_t *task);
-void rr_init(void);
-
-int module_uid;
-
-int idle = 0;
-
-FW_LIST_HEAD(rr_processes);
-FW_SPINLOCK_CREATE(rr_lock);
-
-struct rr_proc_list_elem {
-       fw_list_head_t list;
-       fw_task_t *task;
-};
-
-struct rr_proc_list_elem *rr_current_task = NULL;
-
-struct prpc *current_process;
-
-char rr_buf[120];
-
-
-
-void rr_print_ready_list(void)
-{
-       struct rr_proc_list_elem *tmp;
-
-       fw_printf("Task List:\n");
-
-       fw_list_for_each_entry(tmp, &rr_processes, list){
-               fw_task_info(tmp->task, rr_buf, 120);
-               fw_printf("\t%s\n", rr_buf);
-       }
-}
-
-void rr_schedule(void)
-{
-       struct rr_proc_list_elem *next_task;
-
-       fw_printf("invoked schedule\n");
-       rr_print_ready_list();
-       //printf("invoked schedule! curent task state %d\n", fw_current_task(0)->state);
-
-       os_spinlock(&rr_lock);
-
-       if(fw_current_task(0)->state == RUNNING)
-               fw_list_add_tail(&fw_current_task(0)->list, &rr_processes);
-
-       os_spinunlock(&rr_lock);
-
-       if(fw_list_empty(&rr_processes))
-               printf("start waiting\n");
-
-       while(fw_list_empty(&rr_processes)){
-//             IRQ_ENABLE;
-//             CPU_IDLE;
-//             MEMORY_BARRIER;
-//             IRQ_DISABLE;
-
-       }
-
-       fw_printf("finished waiting\n");
-
-       os_spinlock(&rr_lock);
-
-       fw_printf("ready tasks: %d\n", fw_list_length(&rr_processes));
-
-       next_task = fw_list_pop(&rr_processes, struct rr_proc_list_elem, list);
-
-       current_process = next_task->task->real_task;
-
-//     os_spinlock(&rr_lock);
-       os_spinunlock(&rr_lock);
-
-       fw_printf("dispatching %s\n", os_task_info(next_task->task));
-
-       fw_dispatch(next_task->task);
-}
-
-void rr_task_admit(fw_task_t *task)
-{
-       fw_printf("RR registered creation of %s (%p)\n", os_task_info(task), task);
-
-       struct rr_proc_list_elem *new_task = fw_malloc((fw_size_t) sizeof(struct rr_proc_list_elem));
-       new_task->task = task;
-
-       os_spinlock(&rr_lock);
-
-       fw_list_add_tail(&new_task->list, &rr_processes);
-       rr_current_task = new_task;
-
-       os_spinunlock(&rr_lock);
-}
-
-void rr_task_release(fw_task_t *task)
-{
-       struct rr_proc_list_elem *tmp;
-
-       fw_printf("RR registered deletion of %s (%p)\n", os_task_info(task), task);
-
-       os_spinlock(&rr_lock);
-
-       fw_list_for_each_entry(tmp, &rr_processes, list)
-               if(tmp->task == task)
-               {
-                       fw_list_del(&tmp->list);
-                       fw_free(tmp);
-                       break;
-               }
-
-       fw_printf("RR removed %s (%p)\n", os_task_info(task), task);
-
-       os_spinunlock(&rr_lock);
-}
-
-void rr_task_wait(fw_task_t *task)
-{
-       struct rr_proc_list_elem *tmp;
-
-       fw_printf("RR registered suspension of %s (%p)\n", os_task_info(task), task);
-
-       os_spinlock(&rr_lock);
-
-       fw_printf("%d tasks available\n", fw_list_length(&rr_processes));
-
-       task->state = BLOCKED;
-
-//     current_process = NULL;
-//     os_set_current_task(NULL);
-
-       fw_list_for_each_entry(tmp, &rr_processes, list) {
-               //fw_printf("considering %s (%p) for removal\n", os_task_info(tmp->task), tmp->task);
-
-               if(tmp->task == task)
-               {
-                       fw_list_del(&tmp->list);
-                       fw_free(tmp);
-                       break;
-               }
-       }
-
-       fw_printf("%d tasks remaining\n", fw_list_length(&rr_processes));
-
-       os_spinunlock(&rr_lock);
-
-}
-
-void rr_task_event(fw_task_t *task)
-{
-       struct rr_proc_list_elem *new_task = fw_malloc((fw_size_t) sizeof(struct rr_proc_list_elem));
-       new_task->task = task;
-
-       os_spinlock(&rr_lock);
-
-       task->state = READY;
-       fw_list_add_tail(&new_task->list, &rr_processes);
-
-       os_spinunlock(&rr_lock);
-       fw_printf("task submitted\n");
-}
-
-void rr_init(){
-       module_uid = fw_register_module();
-
-       fw_subscribe(ADMIT, &rr_task_admit);
-       fw_subscribe(RELEASE, &rr_task_release);
-       fw_subscribe(EVENT, &rr_task_event);
-       fw_subscribe(EVENT_WAIT, &rr_task_wait);
-       fw_subscribe(SCHEDULE, &rr_schedule);
-}
diff --git a/sys/framework/os/bertos/os.c b/sys/framework/os/bertos/os.c
deleted file mode 100644 (file)
index 71e98f1..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "../os.h"
-
-#include <stdarg.h>
-
-#include <cfg/debug.h>
-
-#include <cpu/pgm.h>
-#include <cpu/irq.h>
-#include <cpu/types.h>
-#include <cpu/frame.h>
-
-#include <struct/heap.h>
-
-#include <kern/proc.h>
-
-
-HEAP_DEFINE_BUF(os_heap_buf, 1024);
-Heap os_heap;
-
-fw_task_t *current_task = NULL;
-
-void os_set_current_task(fw_task_t *task){
-       current_task = task;
-}
-
-void *os_malloc(fw_size_t size){
-       return heap_malloc(&os_heap, (size_t) size);
-}
-
-void os_free(void* ptr)
-{
-       heap_free(&os_heap, ptr);
-}
-
-void os_create_task(fw_task_t *task)
-{
-       (void) task;
-}
-
-void os_dispatch(fw_task_t *task)
-{
-       cpu_stack_t *dummy;
-
-       fw_task_t *old_task = current_task;
-       current_task = task;
-
-
-       /*
-        * If there is no old process, we save the old stack pointer into a
-        * dummy variable that we ignore.  In fact, this happens only when the
-        * old process has just exited.
-        */
-       //os_printf("switching %x (%x) and %x (%x)\n", ((Process*)(task->real_task))->stack, &((Process*)(task->real_task))->stack, ((Process*)(current_task->real_task))->stack, &((Process*)(current_task->real_task))->stack);
-
-
-       asm_switch_context(&((Process*)(current_task->real_task))->stack, old_task ? &((Process*)(old_task->real_task))->stack : &dummy);
-}
-
-void os_dispatch_mp(fw_task_t *task, int cpu)
-{
-       (void) cpu;
-       os_dispatch(task);
-}
-
-int os_init_os(){
-       kprintf("Initializing for BeRTOS...");
-
-       heap_init(&os_heap, os_heap_buf, sizeof(os_heap_buf));
-
-       kprintf("done!\n");
-       return 0;
-}
-
-inline void os_spinlock(fw_spinlock_t *lock)
-{
-       cpu_flags_t __flags; \
-       IRQ_SAVE_DISABLE(__flags); \
-       while(*lock){
-               IRQ_RESTORE(__flags);
-               CPU_IDLE;
-               MEMORY_BARRIER;
-               IRQ_SAVE_DISABLE(__flags);
-       }
-       *lock = 1;
-       IRQ_RESTORE(__flags);
-}
-
-inline void os_spinunlock(fw_spinlock_t *lock)
-{
-       cpu_flags_t __flags; \
-       IRQ_SAVE_DISABLE(__flags); \
-       *lock = 0;
-       IRQ_RESTORE(__flags);
-}
-
-const char *os_task_info(fw_task_t *task){
-       return task->real_task ? proc_name(task->real_task) : "Invalid Task";
-}
diff --git a/sys/framework/os/bertos/os.h b/sys/framework/os/bertos/os.h
deleted file mode 100644 (file)
index 82842ce..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef BERTOS_OS_H_
-#define BERTOS_OS_H_
-
-#include <cfg/os.h>
-#include <cfg/compiler.h>
-
-#include "cfg/cfg_debug.h"   /* CONFIG_KDEBUG_* */
-
-#include <kern/irq.h>
-
-#ifdef _DEBUG
-       #include <cpu/attr.h>        /* CPU_HARVARD */
-       #if CPU_HARVARD
-               #include <cpu/pgm.h>
-               //void os_printf_P(const char *PROGMEM fmt, ...) FORMAT(__printf__, 1, 2);
-               #define os_printf(fmt, ...)  kprintf_P(PSTR(fmt) ,## __VA_ARGS__)
-       #else /* !CPU_HARVARD */
-               void os_printf(const char *fmt, ...) FORMAT(__printf__, 1, 2);
-       #endif /* !CPU_HARVARD */
-#endif
-
-
-
-
-#endif /* BERTOS_OS_H_ */
diff --git a/sys/framework/os/bertos/os_p.c b/sys/framework/os/bertos/os_p.c
deleted file mode 100644 (file)
index 86eea27..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "../os.h"
-
-#include <stdarg.h>
-
-#include <cfg/debug.h>
-
-#include <cpu/pgm.h>
-
-/*
-void PGM_FUNC(os_printf)(const char * PGM_ATTR fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       PGM_FUNC(kvprintf)(fmt, ap);
-       va_end(ap);
-}*/
diff --git a/sys/framework/os/bertos/rules.mk b/sys/framework/os/bertos/rules.mk
deleted file mode 100644 (file)
index b0199bf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-fw_CPPFLAGS += \
-    -I$(SCHED_PATH)
-    
-fw_USER_CSRC += \
-    $(SCHED_PATH)/fw.c \
-    $(SCHED_PATH)/fw_comm.c \
-    $(SCHED_PATH)/fw_list.c \
-    $(SCHED_PATH)/fw_modules.c \
-    $(SCHED_PATH)/modules/round_robin.c \
-    $(SCHED_PATH)/os/bertos/os.c 
-
-# Files included by the user.
-fw_USER_PCSRC += \
-    $(SCHED_PATH)/os/bertos/os_p.c
diff --git a/sys/framework/os/freebsd/fbsd_sched.c b/sys/framework/os/freebsd/fbsd_sched.c
deleted file mode 100644 (file)
index 5eeab9f..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * fbsd_sched.c
- *
- *  Created on: 11.12.2013
- *  Author: jkrieg, anton.e
- */
-
-#include "sys/param.h"
-#include "sys/systm.h"
-#include "sys/proc.h"
-#include "sys/sysctl.h"
-#include "sys/sched.h"
-
-
-
-
-
-/**
- * \brief      Called from proc0_init() to setup the scheduler fields.
- */
-void schedinit(void)
-{
-
-}
-
-/**
- * \brief      Update the remaining time slice of the thread.
- *
- * @param      td              Thread that shall be modified.
- */
-void sched_clock(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Called once per hz tick.
- *
- * @param      cnt
- */
-void sched_tick(int cnt)
-{
-       /* Empty by design. */
-}
-
-/**
- * \brief      The actual idle process.
- *
- * @param      dummy   Free to abusse.
- */
-void sched_idletd(void *dummy)
-{
-
-}
-
-/**
- * \brief      Switch threads. This function has to handle threads coming in while
- *                     blocked for some reason, running, or idle. It also must deal with
- *                     migrating a thread from one queue to another as running threads may
- *                     be assigned elsewhere via binding.
- *
- * @param      td              Running thread.
- * @param      newtd   Should always be NULL.
- * @param      flags   Flags can be consider in the scheduling decision.
- */
-void sched_switch(struct thread *td, struct thread *newtd, int flags)
-{
-
-}
-
-/**
- * \brief      Penalize the parent for creating a new child and initialize the child's
- *                     priority.
- *
- * @param      td              Parent.
- * @param      child   Thread to be forked from parent.
- */
-void sched_fork(struct thread *td, struct thread *child)
-{
-
-}
-
-/**
- * \brief      Fork a new thread, may be within the same process.
- *
- * @param      td              Parent.
- * @param      child   Thread to be forked from parent.
- */
-void sched_fork_thread(struct thread *td, struct thread *child)
-{
-
-}
-
-/**
- * \brief      This is called from fork_exit(). Just acquire the correct locks and
- *                     let fork do the rest of the work.
- *
- * @param      td              Thread that shall be forked soon.
- */
-void sched_fork_exit(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Choose the highest priority thread to run. The thread is removed from
- *                     the run-queue while running however the load remains.
- *
- * @return     Next thread to run.
- */
-struct thread* sched_choose(void)
-{
-       return 0;
-}
-
-/**
- * \brief      Select the target thread queue and add a thread to it. Request
- *                     preemption or IPI a remote processor if required.
- *
- * @param      td              Thread add to e.g. a run-queue
- * @param      flags   Properties of the new thread.
- */
-void sched_add(struct thread *td, int flags)
-{
-
-}
-
-/**
- * \brief      Schedule a thread to resume execution and record how long it voluntarily
- *                     slept. We also update the pctcpu, interactivity, and priority.
- *
- * @param      td              Thread that shall be woken.
- */
-void sched_wakeup(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Adjust the priority class of a thread.
- *
- * @param      td              Thread to be modified.
- * @param      class   Scheduling class.
- */
-void sched_class(struct thread *td, int class)
-{
-
-}
-
-/**
- * \brief      Return some of the child's priority and interactivity to the parent.
- *
- * @param      p               Parent process.
- * @param      child   Thread that shall be penalized in priority.
- */
-void sched_exit(struct proc *p, struct thread *child)
-{
-
-}
-
-/**
- * \brief      Penalize another thread for the time spent on this one. This helps to
- *                     worsen the priority and interactivity of processes which schedule batch
- *                     jobs such as make. This has little effect on the make process itself but
- *                     causes new processes spawned by it to receive worse scores immediately.
- *
- * @param      td              Parent process.
- * @param      child   Thread to be forked from parent.
- */
-void sched_exit_thread(struct thread *td, struct thread *child)
-{
-
-}
-
-/**
- * \brief      Update a thread's priority when it is lent another thread's
- *                     priority.
- *
- * @param      td              Thread that shall be modified.
- * @param      prio    Lent priority value of another thread.
- */
-void sched_lend_prio(struct thread *td, u_char prio)
-{
-
-}
-
-/**
- * \brief      Restore a thread's priority when priority propagation is
- *                     over. The prio argument is the minimum priority the thread
- *                     needs to have to satisfy other possible priority lending
- *                     requests. If the thread's regular priority is less
- *                     important than prio, the thread will keep a priority boost
- *                     of prio.
- *
- * @param      td              Thread that shall be modified.
- * @param      prio    Old priority value of the thread.
- */
-void sched_unlend_prio(struct thread *td, u_char prio)
-{
-
-}
-
-/**
- * \brief      Standard entry for setting the priority to an absolute value.
- *
- * @param      td              Thread that shall be modified.
- * @param      prio    Set the priority value of the given thread.
- */
-void sched_prio(struct thread *td, u_char prio)
-{
-
-}
-
-/**
- * \brief      Set the base user priority, does not effect current running priority.
- *
- * @param      td              Thread that shall be modified.
- * @param      prio    Set user base priority value of the given thread.
- */
-void sched_user_prio(struct thread *td, u_char prio)
-{
-
-}
-
-/**
- * \brief      Update a thread's user priority when it is lent another thread's user
- *                     priority.
- *
- * @param      td              Thread that shall be modified.
- * @param      prio    Lent user priority value of another thread.
- */
-void sched_lend_user_prio(struct thread *td, u_char prio)
-{
-
-}
-
-/**
- * \brief      Fix priorities on return to user-space. Priorities may be elevated due
- *                     to static priorities in msleep() or similar.
- *
- * @param      td              Thread that shall be modified.
- */
-void sched_userret(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Used by void ipi_bitmap_handler(struct trapframe frame);
- *                     sys/amd64/amd64/mp_machdep.c:1267
- *
- * @param      td              Thread to be preemted.
- */
-void sched_preempt(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Basic yield call.
- *
- * @param      td              Thread that yields.
- */
-void sched_relinquish(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Adjust thread priorities as a result of a nice request.
- *
- * @param      p               Process pointer.
- * @param      nice    Set nice value of process and change his priority as well.
- */
-void sched_nice(struct proc *p, int nice)
-{
-
-}
-
-/**
- * \brief      Enforce affinity settings for a thread. Called after adjustments to
- *                     cpumask.
- *
- * @param      td              Thread shall be modified.
- */
-void sched_affinity(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Bind a thread to a target cpu.
- *
- * @param      td              Thread that should be bind to a certain CPU.
- * @param      cpu             Specific CPU for the thread.
- */
-void sched_bind(struct thread *td, int cpu)
-{
-
-}
-
-/**
- * \brief      Release a bound thread.
- *
- * @param      td              Unbind this thread.
- */
-void sched_unbind(struct thread *td)
-{
-
-}
-
-/**
- * \brief      Validates the current bind status of a thread.
- *
- * @param      td              Check this thread
- * @return     0: not bound, 1: bounded
- */
-int sched_is_bound(struct thread *td)
-{
-       return 0;
-}
-
-/**
- * \brief      This is only somewhat accurate since given many processes of the same
- *                     priority they will switch when their slices run out, which will be
- *                     at most sched_slice stathz ticks.
- *
- * @return     Returns a time slice in Hz.
- */
-int sched_rr_interval(void)
-{
-       return 0;
-}
-
-/**
- * \brief      Record the sleep time for the interactivity scorer.
- *
- * @param      td              Thread that shall be modified.
- * @param      prio    Priority value set to the thread and store the sleep time.
- */
-void sched_sleep(struct thread *td, int prio)
-{
-
-}
-
-/**
- * \brief      Return whether the current CPU has runnable tasks. Used for in-kernel
- *                     cooperative idle threads.
- *
- * @return     0: no load, 1: load
- */
-int sched_runnable(void)
-{
-       return 0;
-}
-
-/**
- * \brief      Fetch cpu utilization information. Updates on demand.
- *
- * @param      td              Thread to be evaluated.
- * @return     CPU utilization of the thread.
- */
-fixpt_t sched_pctcpu(struct thread *td)
-{
-       return 0;
-}
-
-/**
- * \brief      Return the total system load.
- *
- * @return     Total system load.
- */
-int sched_load(void)
-{
-       return 0;
-}
-
-/**
- * \brief      Gather the whole process structure size.
- *
- * @return     Process structure size in byte.
- */
-int sched_sizeof_proc(void)
-{
-       return 0;
-}
-
-/**
- * \brief      Gather the complete thread structure size.
- *
- * @return     Thread structure size in byte.
- */
-int sched_sizeof_thread(void)
-{
-       return 0;
-}
-
-/**
- * \brief      A CPU is entering for the first time or a thread is exiting.
- *
- * @param      td              Thread to be thrown away. Choose a new one to be scheduled.
- */
-void sched_throw(struct thread *td)
-{
-
-}
-
-/**
- * \brief      ???
- */
-SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler");
diff --git a/sys/framework/os/freebsd/os.c b/sys/framework/os/freebsd/os.c
deleted file mode 100644 (file)
index aba3742..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * os.c
- *
- *  Created on: 04.12.2013
- *      Author: jkrieg
- */
-
-#include "os.h"
-
-
-/**
- * CPU dependent context switching routines.
- *
- * Saving and restoring the context on the stack is done by a CPU-dependent
- * support routine which usually needs to be written in assembly.
- */
-//EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp);
-
-//HEAP_DEFINE_BUF(os_heap_buf, 1024);
-//Heap os_heap;
-
-
-void *os_malloc(fw_size_t size){
-//     return heap_malloc(&os_heap, (size_t) size);
-       return 0;
-}
-
-void os_free(void* ptr)
-{
-//     heap_free(&os_heap, ptr);
-}
-
-
-int os_init_os(){
-       printf("Initializing for BeRTOS...");
-
-//     heap_init(&os_heap, os_heap_buf, sizeof(os_heap_buf));
-
-       printf("done!\n");
-       return 0;
-}
-
diff --git a/sys/framework/os/freebsd/os_kdb.c b/sys/framework/os/freebsd/os_kdb.c
deleted file mode 100644 (file)
index fd2036b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * kdb.c
- *
- *  Created on: 10.12.2013
- *      Author: jkrieg
- */
-
-#include "os.h"
-#include "os_kdb.h"
-
-
-
-int os_task_name(fw_task_t *task, char *buf, fw_size_t size)
-{
-       return strlcpy(buf, os_task_info(task), size);
-}
-
-const char *os_task_info(fw_task_t *task){
-//     return task ? (task->real_task ? proc_name(task->real_task) : "Invalid Task") : "<NULL>";
-       return 0;
-}
diff --git a/sys/framework/os/freebsd/os_lock.c b/sys/framework/os/freebsd/os_lock.c
deleted file mode 100644 (file)
index 76f43a0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * lock.c
- *
- *  Created on: 10.12.2013
- *      Author: jkrieg
- */
-
-#include "os.h"
-#include "os_lock.h"
-
-
-
-inline void os_spinlock(fw_spinlock_t *lock)
-{
-//     cpu_flags_t __flags; \
-//     IRQ_SAVE_DISABLE(__flags); \
-//     while(*lock){
-//             IRQ_RESTORE(__flags);
-//             CPU_IDLE;
-//             MEMORY_BARRIER;
-//             IRQ_SAVE_DISABLE(__flags);
-//     }
-//     *lock = 1;
-//     IRQ_RESTORE(__flags);
-}
-
-inline void os_spinunlock(fw_spinlock_t *lock)
-{
-//     cpu_flags_t __flags; \
-//     IRQ_SAVE_DISABLE(__flags); \
-//     *lock = 0;
-//     IRQ_RESTORE(__flags);
-}
diff --git a/sys/framework/os/freebsd/os_sched.c b/sys/framework/os/freebsd/os_sched.c
deleted file mode 100644 (file)
index 646333d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * sched.c
- *
- *  Created on: 10.12.2013
- *      Author: jkrieg
- */
-
-#include "os.h"
-#include "os_sched.h"
-
-
-
-fw_task_t *current_task = NULL;
-
-
-void os_dispatch(fw_task_t *task)
-{
-//     cpu_stack_t *dummy;
-//
-//
-//
-//     fw_task_t *old_task;
-//     old_task = current_task;
-//
-//
-//     os_set_current_task(task);
-//
-//     os_printf("switching from '%s' (%p) to '%s' (%p)\n", os_task_info(old_task), old_task, os_task_info(current_task), current_task);
-//     os_printf("switching stack from %x (%p) &(%p) to %x (%p) &(%p)\n", *((Process*)(old_task->real_task))->stack, ((Process*)(old_task->real_task))->stack, &((Process*)(old_task->real_task))->stack, *((Process*)(current_task->real_task))->stack, ((Process*)(current_task->real_task))->stack, &((Process*)(current_task->real_task))->stack);
-//
-//     /*
-//      * If there is no old process, we save the old stack pointer into a
-//      * dummy variable that we ignore.  In fact, this happens only when the
-//      * old process has just exited.
-//      */
-//     asm_switch_context(&((Process*)(current_task->real_task))->stack, old_task ? &((Process*)(old_task->real_task))->stack : &dummy);
-}
-
-void os_dispatch_mp(fw_task_t *task, int cpu)
-{
-//     (void) cpu;
-//     os_dispatch(task);
-}
-
-fw_task_t *os_current_task(int cpu){
-       (void) cpu;
-
-//     return proc_current()->fw_task;
-       return 0;
-}
-
-void os_set_current_task(fw_task_t *task){
-       current_task = task;
-       printf("current_task set to %p\n", task);
-}
diff --git a/sys/framework/os/linux/Makefile b/sys/framework/os/linux/Makefile
deleted file mode 100644 (file)
index 43b91a8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-MOD_NAME=mod_sched
-FLAGS=$(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR($(MOD_NAME))"  -D"KBUILD_MODNAME=KBUILD_STR($(MOD_NAME))" -c
-
-OBJ+=$(MOD_SCHED_DIR)/os/linux/os.o
-
-## Compile the framework and the modules to one object mod_sched.o
-mod_sched_build: $(OBJ)
-       @echo "--- Scheduler-Module Linking... ---"
-       $(LD) -o kernel/sched.new/mod_sched.o $(OBJ) -r
-       # Use printk whenever fw_printf is called
-       objcopy --redefine-sym fw_printf=printk kernel/sched.new/mod_sched.o
-       @echo "--- Scheduler-Module Linked! ---"                
-       
-%.o: %.c
-       @echo "--- Scheduler-Module $@ Compiling... "
-       $(CC) $(LINUXINCLUDE) -I$(MOD_SCHED_DIR) $(FLAGS) $< -o $@
-       
-.PHONY: clean
-clean:
-       @echo "--- Removing Old Scheduler Modules ---"
-       rm -f $(MOD_SCHED_DIR)/*.o $(MOD_SCHED_DIR)/modules/*.o $(MOD_SCHED_DIR)/os/linux/*.o
diff --git a/sys/framework/os/linux/linux_sched.c b/sys/framework/os/linux/linux_sched.c
deleted file mode 100644 (file)
index 8f3f947..0000000
+++ /dev/null
@@ -1,967 +0,0 @@
-/*
- * linux_sched.c
- *
- *  Created on: 11.12.2013
- *      Author: jkrieg
- */
-
-#include <linux/init.h>
-#include <asm/mmu_context.h>
-#include <linux/completion.h>
-#include <linux/kernel_stat.h>
-#include <linux/blkdev.h>
-#include <linux/syscalls.h>
-#include <linux/kprobes.h>
-#include <linux/delayacct.h>
-#include <linux/export.h>
-#include <linux/context_tracking.h>
-#include <linux/kthread.h>
-#include <linux/init_task.h>
-
-#include <asm/switch_to.h>
-#include <asm/tlb.h>
-#include <linux/cgroup.h>
-#include "sched.h"
-#include "../workqueue_internal.h"
-#include "../smpboot.h"
-
-
-
-/*
- * kernel/sched/rt.c:10
- * default timeslice is 100 msecs (used only for SCHED_RR tasks).
- * Timeslices get refilled after they expire. RR_TIMESLICE is defined as
- * (100 * HZ / 1000) and is assigned to sched_rr_timeslice.
- */
-int sched_rr_timeslice = RR_TIMESLICE;
-
-/*
- * kernel/sched/fair.c:80
- * After fork, child runs first. If set to 0 (default) then
- * parent will (try to) run first.
- */
-unsigned int sysctl_sched_child_runs_first = 0;
-
-/*
- * kernel/sched/core.c:289
- * Period over which we measure -rt task cpu usage in us.
- * default: 1s (1000000)
- */
-unsigned int sysctl_sched_rt_period = 1000000;
-
-/*
- * /kernel/sched/core.c:2081
- * Variables and functions for calc_load
- */
-unsigned long avenrun[3];
-
-/*
- * kernel/sched/core.c:297
- * part of the period that we allow rt tasks to run in us.
- * default: 0.95s (950000)
- */
-int sysctl_sched_rt_runtime = 950000;
-
-/*
- * /kernel/sched/core.c:8024
- * No idea.
- */
-struct cgroup_subsys cpu_cgroup_subsys;
-
-/*
- * /kernel/sched/core.c:8251
- * No idea.
- */
-struct cgroup_subsys cpuacct_subsys;
-
-/*
- * /kernel/sched/core.c:6866
- *
- */
-struct task_group root_task_group;
-
-/*
- * /kernel/sched/core.c:2623
- * unknown
- */
-DEFINE_PER_CPU(struct kernel_stat, kstat);
-DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
-
-
-
-
-
-
-/**
- * kernel/sched/core.c:6872
- * Initialize the scheduler
- */
-void sched_init(void)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:6850
- */
-void sched_init_smp(void)
-{
-    return;
-}
-
-/**
- * /kernel/sched/core.c:4674
- * init_idle - set up an idle thread for a given CPU
- * @idle: task in question
- * @cpu: cpu the idle task belongs to
- *
- * NOTE: this function does not set the idle thread's NEED_RESCHED
- * flag, to make booting more robust.
- */
-void __cpuinit init_idle(struct task_struct *idle, int cpu)
-{
-    return;
-}
-
-/*
- * /kernel/sched/core.c:4669
- * Sets sched_class of idle task, see struct sched_class idle_sched_class;
- */
-void __cpuinit init_idle_bootup_task(struct task_struct *idle)
-{
-    return;
-}
-
-/*
- * kernel/sched/clock.c:350
- * Initialize/Start scheduler clock.
- */
-void sched_clock_init(void)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:2684
- * This function gets called by the timer code, with HZ frequency.
- * We call it with interrupts disabled.
- */
-void scheduler_tick(void)
-{
-    return;
-}
-
-/**
- * sched_clock_cpu - returns current time in nanosec units
- * using scheduler clock function.
- * @param: cpu id
- */
-u64 sched_clock_cpu(int cpu)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:892
- * task_curr - is this task currently executing on a CPU?
- * @p: the task in question.
- */
-inline int task_curr(const struct task_struct *p)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3768
- * idle_task - return the idle task for a given cpu.
- * @cpu: the processor in question.
- */
-struct task_struct *idle_task(int cpu)
-{
-    return 0;
-}
-
-/**
- * /kernel/sched/core.c:3742
- * idle_cpu - is a given cpu idle currently?
- * @cpu: the processor in question.
- */
-int idle_cpu(int cpu)
-{
-    return 0;
-}
-
-/*
- * kernel/sched/core.c:2966
- */
-asmlinkage void __sched schedule(void)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:1622
- * fork()/clone()-time setup:
- */
-void sched_fork(struct task_struct *p)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:1905
- * schedule_tail - first thing a freshly forked thread must call.
- * @prev: the thread we just switched away from.
- */
-void schedule_tail(struct task_struct *prev)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:1703
- * wake_up_new_task - wake up a newly created task for the first time.
- *
- * This function will do some initial scheduler statistics housekeeping
- * that must be done for every newly created context, then puts the task
- * on the runqueue and wakes it.
- */
-void wake_up_new_task(struct task_struct *tsk)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:1536
- * wake_up_process - Wake up a specific process
- * @p: The process to be woken up.
- *
- * Attempt to wake up the nominated process and move it to the set of runnable
- * processes.  Returns 1 if the process was woken up, 0 if it was already
- * running.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-int wake_up_process(struct task_struct *p)
-{
-    return 0;
-}
-
-/*
- * kernel/sched/core.c:4333
- */
-int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags, void *key)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3149
- * __wake_up - wake up threads blocked on a waitqueue.
- * @q: the waitqueue
- * @mode: which threads
- * @nr_exclusive: how many wake-one or wake-many threads to wake up
- * @key: is directly passed to the wakeup function
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, void *key)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:1543
- */
-int wake_up_state(struct task_struct *p, unsigned int state)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3213
- * __wake_up_sync - see __wake_up_sync_key()
- */
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3192
- * __wake_up_sync_key - wake up threads blocked on a waitqueue.
- * @q: the waitqueue
- * @mode: which threads
- * @nr_exclusive: how many wake-one or wake-many threads to wake up
- * @key: opaque value to be passed to wakeup targets
- *
- * The sync wakeup differs that the waker knows that it will schedule
- * away soon, so while the target thread will be woken up, it will not
- * be migrated to another CPU - ie. the two threads are 'synchronized'
- * with each other. This can prevent needless bouncing between CPUs.
- *
- * On UP it can prevent extra preemption.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
-            int nr_exclusive, void *key)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3163
- * Same as __wake_up but called with the spinlock in wait_queue_head_t held.
- */
-void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3169
- */
-void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3231
- * complete: - signals a single thread waiting on this completion
- * @x:  holds the state of this particular completion
- *
- * This will wake up a single thread waiting on this completion. Threads will be
- * awakened in the same order in which they were queued.
- *
- * See also complete_all(), wait_for_completion() and related routines.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void complete(struct completion *x)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3251
- * complete_all: - signals all threads waiting on this completion
- * @x:  holds the state of this particular completion
- *
- * This will wake up all threads waiting on this particular completion event.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void complete_all(struct completion *x)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3322
- * wait_for_completion: - waits for completion of a task
- * @x:  holds the state of this particular completion
- *
- * This waits to be signaled for completion of a specific task. It is NOT
- * interruptible and there is no timeout.
- *
- * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
- * and interrupt capability. Also see complete().
- */
-void __sched wait_for_completion(struct completion *x)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3341
- * wait_for_completion_timeout: - waits for completion of a task (w/timeout)
- * @x:  holds the state of this particular completion
- * @timeout:  timeout value in jiffies
- *
- * This waits for either a completion of a specific task to be signaled or for a
- * specified timeout to expire. The timeout is in jiffies. It is not
- * interruptible.
- *
- * The return value is 0 if timed out, and positive (at least 1, or number of
- * jiffies left till timeout) if completed.
- */
-unsigned long __sched wait_for_completion_timeout(struct completion *x, unsigned long timeout)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3355
- * wait_for_completion_io: - waits for completion of a task
- * @x:  holds the state of this particular completion
- *
- * This waits to be signaled for completion of a specific task. It is NOT
- * interruptible and there is no timeout. The caller is accounted as waiting
- * for IO.
- */
-void __sched wait_for_completion_io(struct completion *x)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3426
- * wait_for_completion_killable: - waits for completion of a task (killable)
- * @x:  holds the state of this particular completion
- *
- * This waits to be signaled for completion of a specific task. It can be
- * interrupted by a kill signal.
- *
- * The return value is -ERESTARTSYS if interrupted, 0 if completed.
- */
-int __sched wait_for_completion_killable(struct completion *x)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4474
- * This task is about to go to sleep on IO. Increment rq->nr_iowait so
- * that process accounting knows that this is a task in IO wait state.
- */
-void __sched io_schedule(void)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:4489
- */
-long __sched io_schedule_timeout(long timeout)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4389
- * yield - yield the current processor to other threads.
- *
- * Do not ever use this function, there's a 99% chance you're doing it wrong.
- *
- * The scheduler is at all times free to pick the calling task as the most
- * eligible task to run, if removing the yield() call from your code breaks
- * it, its already broken.
- *
- * Typical broken usage is:
- *
- * while (!event)
- *     yield();
- *
- * where one assumes that yield() will let 'the other' process run that will
- * make event true. If the current task is a SCHED_FIFO task that will never
- * happen. Never use yield() as a progress guarantee!!
- *
- * If you want to use yield() to wait for something, use wait_event().
- * If you want to use yield() to be 'nice' for others, use cond_resched().
- * If you still want to use yield(), do not!
- */
-void __sched yield(void)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:2995
- * schedule_preempt_disabled - called with preemption disabled
- *
- * Returns with preemption disabled. Note: preempt_count must be 1
- */
-void __sched schedule_preempt_disabled(void)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:4315
- */
-int __sched _cond_resched(void)
-{
-    return 0;
-}
-
-/*
- * kernel/sched/core.c:4333
- * __cond_resched_lock() - if a reschedule is pending, drop the given lock,
- * call schedule, and on return reacquire the lock.
- *
- * This works OK both with and without CONFIG_PREEMPT. We do strange low-level
- * operations here to prevent schedule() from being called twice (once via
- * spin_unlock(), once by hand).
- */
-int __cond_resched_lock(spinlock_t *lock)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3736
- * task_nice - return the nice value of a given task.
- * @p: the task in question.
- */
-int task_nice(const struct task_struct *p)
-{
-    return 0;
-}
-
-/*
- * /kernel/sched/core.c:3668
- * Check if a task can reduce its nice value
- * @p: task
- * @nice: nice value
- */
-int can_nice(const struct task_struct *p, const int nice)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3616
- */
-void set_user_nice(struct task_struct *p, long nice)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3727
- * task_prio - return the priority value of a given task.
- * @p: the task in question.
- *
- * This is the priority value as seen by users in /proc.
- * RT tasks are offset by -200. Normal tasks are centered
- * around 0, value goes from -16 to +15.
- */
-int task_prio(const struct task_struct *p)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4111
- * This function installs the cpusetsize bytes long affinity mask pointed to by cpuset for the process or
- * thread with the ID pid. If successful the function returns zero and the scheduler will in future take the
- * affinity information into account.
- */
-long sched_setaffinity(pid_t pid, const struct cpumask *new_mask)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4213
- * This functions stores the CPU affinity mask for the process or thread with the ID pid in the cpusetsize
- * bytes long bitmap pointed to by cpuset. If successful, the function always initializes all bits in the
- * cpu_set_t object and returns zero.
- *
- * If pid does not correspond to a process or thread on the system the or the function fails for some other
- * reason, it returns -1 and errno is set to represent the error condition.
- */
-long sched_getaffinity(pid_t pid, struct cpumask *mask)
-{
-    return 0;
-}
-
-/*
- * kernel/sched/core.c:2667
- * Return accounted runtime for the task.
- * In case the task is currently running, return the runtime plus current's
- * pending runtime that have not been accounted yet.
- */
-unsigned long long task_sched_runtime(struct task_struct *task)
-{
-    return 0;
-}
-
-/*
- * /kernel/sched/cputime.c:436
- * Account multiple ticks of idle time.
- * @ticks: number of stolen ticks
- */
-void account_idle_ticks(unsigned long ticks)
-{
-    return;
-}
-
-/*
- * /kernel/sched/cputime.c:397
- * Account a single tick of cpu time.
- * @p: the process that the cpu time gets accounted to
- * @user_tick: indicates if the tick is a user or a system tick
- */
-void account_process_tick(struct task_struct *p, int user_tick)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:2024
- * this_cpu_load - returns load of the cpu
- */
-unsigned long this_cpu_load(void)
-{
-    return 0;
-}
-
-/*
- * /kernel/sched/core.c:2363
- * calc_load - update the avenrun load estimates 10 ticks after the
- * CPUs have updated calc_load_tasks.
- */
-void calc_global_load(unsigned long ticks)
-{
-    return;
-}
-
-/*
- * /kernel/sched/core.c:2197
- * We're going into NOHZ mode, if there's any pending delta, fold it
- * into the pending idle delta.
- */
-void calc_load_enter_idle(void)
-{
-    return;
-}
-
-/*
- * /kernel/sched/core.c:2213
- * If we're still before the sample window, we're done.
- *
- * We woke inside or after the sample window, this means we're already
- * accounted through the nohz accounting, so skip the entire deal and
- * sync up for the next window.
- */
-void calc_load_exit_idle(void)
-{
-    return;
-}
-
-/*
- * kernel/sched/core.c:2649
- * Lock/unlock the current runqueue - to extract task statistics:
- */
-unsigned long long task_delta_exec(struct task_struct *p)
-{
-    return 0;
-}
-
-/*
- * kernel/sched/core.c:2556
- * update_cpu_load_nohz - called from tick_nohz_idle_exit() -- try and fix up the ticks we missed.
- */
-void update_cpu_load_nohz(void)
-{
-    return;
-}
-
-/*
- * /kernel/sched/core.c:2092
- * get_avenrun - get the load average array
- * @loads:    pointer to dest load array
- * @offset:    offset to add
- * @shift:    shift count to shift the result left
- *
- * These values are estimates at best, so no need for locking.
- */
-void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
-{
-    return;
-}
-
-/*
- * /kernel/sched/core.c:1997
- * nr_running and nr_context_switches:
- *
- * externally visible scheduler statistics:
- *   current number of runnable threads
- *   total number of context switches performed since bootup.
- */
-unsigned long nr_running(void)
-{
-    return 0;
-}
-
-unsigned long long nr_context_switches(void)
-{
-    return 0;
-}
-
-/*
- * /kernel/sched/core.c:2017
- * number of threads waiting on IO
- */
-unsigned long nr_iowait(void)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:2018
- */
-unsigned long nr_iowait_cpu(int cpu)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4601
- */
-void sched_show_task(struct task_struct *p)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:4634
- */
-void show_state_filter(unsigned long state_filter)
-{
-    return;
-}
-
-/*
- * /kernel/sched/core.c:7108
- * Calls private function
- * static void normalize_task(struct rq *rq, struct task_struct *p)
- */
-void normalize_rt_tasks(void)
-{
-    return;
-}
-
-/*
- * rt_mutex_setprio - set the current priority of a task
- * @p: task
- * @prio: prio value (kernel-internal form)
- *
- * This function changes the 'effective' priority of a task. It does
- * not touch ->normal_prio like __setscheduler().
- *
- * Used by the rt_mutex code to implement priority inheritance logic.
- */
-void rt_mutex_setprio(struct task_struct *p, int prio)
-{
-    return;
-}
-
-/**
- * kernel/sched/core.c:3975
- * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
- * @p: the task in question.
- * @policy: new policy.
- * @param: structure containing the new RT priority.
- *
- * NOTE that the task may be already dead.
- */
-int sched_setscheduler(struct task_struct *p, int policy,
-        const struct sched_param *param)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:3993
- * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.
- * @p: the task in question.
- * @policy: new policy.
- * @param: structure containing the new RT priority.
- *
- * Just like sched_setscheduler, only don't bother checking if the
- * current context has permission.  For example, this is needed in
- * stop_machine(): we create temporary high priority worker threads,
- * but our caller might not have that capability.
- */
-int sched_setscheduler_nocheck(struct task_struct *p, int policy,
-const struct sched_param *param)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:7590
- */
-int sched_rt_handler(struct ctl_table *table, int write,
-        void __user *buffer, size_t *lenp,
-        loff_t *ppos)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:7571
- */
-int sched_rr_handler(struct ctl_table *table, int write,
-        void __user *buffer, size_t *lenp,
-        loff_t *ppos)
-{
-    return 0;
-}
-
-/*
- * kernel/sched/core.c:6858
- */
-int in_sched_functions(unsigned long addr)
-{
-    return 0;
-}
-
-
-
-
-/*
- * Syscalls
- *
- * Help:
- * SYSCALL_DEFINEx will be replaced by asmlinkage data_type function_name
- * asmlinkage:     tells the compile that the arguments of the function are
- *                 not placed in the registers but rather to find on stack
- */
-
-/*
- * kernel/sched/core.c:3686
- * sys_nice - change the priority of the current process.
- * @increment: priority increment
- *
- * sys_setpriority is a more generic, but much slower function that
- * does similar things.
- */
-SYSCALL_DEFINE1(nice, int, increment)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4248
- * sys_sched_getaffinity - get the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to hold the current cpu mask
- */
-SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
-        unsigned long __user *, user_mask_ptr)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4197
- * sys_sched_setaffinity - set the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to the new cpu mask
- */
-SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
-        unsigned long __user *, user_mask_ptr)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4562
- * sys_sched_rr_get_interval - return the default timeslice of a process.
- * @pid: pid of the process.
- * @interval: userspace pointer to the timeslice value.
- *
- * this syscall writes the default timeslice value of a given process
- * into the user-space timespec buffer. A value of '0' means infinity.
- */
-SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
-        struct timespec __user *, interval)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4282
- * sys_sched_yield - yield the current processor to other threads.
- *
- * This function yields the current CPU to other tasks. If there are no
- * other threads running on this CPU then this function will return.
- */
-SYSCALL_DEFINE0(sched_yield)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4027
- * sys_sched_setscheduler - set/change the scheduler policy and RT priority
- * @pid: the pid in question.
- * @policy: new policy.
- * @param: structure containing the new RT priority.
- */
-SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy,
-        struct sched_param __user *, param)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4051
- * sys_sched_getscheduler - get the policy (scheduling class) of a thread
- * @pid: the pid in question.
- */
-SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4512
- * sys_sched_get_priority_max - return maximum RT priority.
- * @policy: scheduling class.
- *
- * this syscall returns the maximum rt_priority that can be used
- * by a given scheduling class.
- */
-SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4537
- * sys_sched_get_priority_min - return minimum RT priority.
- * @policy: scheduling class.
- *
- * this syscall returns the minimum rt_priority that can be used
- * by a given scheduling class.
- */
-SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4042
- * sys_sched_setparam - set/change the RT priority of a thread
- * @pid: the pid in question.
- * @param: structure containing the new RT priority.
- */
-SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
-{
-    return 0;
-}
-
-/**
- * kernel/sched/core.c:4077
- * sys_sched_getparam - get the RT priority of a thread
- * @pid: the pid in question.
- * @param: structure containing the RT priority.
- */
-SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
-{
-    return 0;
-}
-
diff --git a/sys/framework/os/linux/os.c b/sys/framework/os/linux/os.c
deleted file mode 100644 (file)
index 2780dbf..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * os.c
- *
- * Map framework functionality to operating system
- * depend functions.
- *
- *  Created on: 11.07.2013
- *      Author: Daniel Roehrig, Christian Rene Sechting
- */
-#include <fw_task.h>
-#include <fw_types.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-//TODO This avoids copying the sched.h into the folder
-#include "../../../kernel/sched.new/sched.h"
-#include <fw.h>
-
-
-extern struct fw_task *fw_idle_task;
-extern void context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next);
-
-void *os_malloc(fw_size_t size)
-{
-       return kmalloc(size,GFP_KERNEL);
-}
-
-void os_free(void *ptr)
-{
-       return;
-}
-
-void os_create_task(fw_task_t *task)
-{
-       return;
-}
-
-
-void os_dispatch_mp(fw_task_t *task, int cpu)
-{
-       struct rq *rq;
-       struct task_struct *prev, *next;
-
-       cpu = smp_processor_id();
-       rq = cpu_rq(cpu);
-       prev = rq->curr;
-       next = (struct task_struct*)task->real_task;
-
-       next->se.exec_start = rq->clock_task;
-       clear_tsk_need_resched(prev);
-       rq->skip_clock_update = 0;
-       rq->nr_switches++;
-       rq->curr = next;
-
-       if(prev != next){
-               context_switch(rq,prev,next);
-               arch_local_irq_enable();
-       }else{
-               raw_spin_unlock_irq(&rq->lock);
-       }
-}
-
-void os_dispatch(fw_task_t *task)
-{
-       int cpu;
-       cpu = smp_processor_id();
-       os_dispatch_mp(task, cpu);
-}
-
-int os_init_os(void)
-{
-       struct task_struct* ptr = current;
-       fw_idle_task = (struct fw_task *)fw_malloc(sizeof(struct fw_task));
-       ptr->fw_task = fw_idle_task;
-       fw_idle_task->real_task = ptr;
-       return 0;
-}
index b27ab5b..1d16941 100644 (file)
-///*-
-// * Copyright (c) 2002-2007, Jeffrey Roberson <jeff@freebsd.org>
-// * All rights reserved.
-// *
-// * Redistribution and use in source and binary forms, with or without
-// * modification, are permitted provided that the following conditions
-// * are met:
-// * 1. Redistributions of source code must retain the above copyright
-// *    notice unmodified, this list of conditions, and the following
-// *    disclaimer.
-// * 2. Redistributions in binary form must reproduce the above copyright
-// *    notice, this list of conditions and the following disclaimer in the
-// *    documentation and/or other materials provided with the distribution.
-// *
-// * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-// * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-// * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-// * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-// * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-// * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-// * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// */
-//
-///*
-// * This file implements the ULE scheduler.  ULE supports independent CPU
-// * run queues and fine grain locking.  It has superior interactive
-// * performance under load even on uni-processor systems.
-// *
-// * etymology:
-// *   ULE is the last three letters in schedule.  It owes its name to a
-// * generic user created for a scheduling system by Paul Mikesell at
-// * Isilon Systems and a general lack of creativity on the part of the author.
-// */
-//
-///*
-// * TODO:
-// */
-//
-//#include <sys/cdefs.h>
-//__FBSDID("$FreeBSD$");
-//
-//#include "opt_hwpmc_hooks.h"
-//#include "opt_kdtrace.h"
-//#include "opt_sched.h"
-//
-//#ifdef FW_MOD_SCHED
-//#include "fw.h"
-//#endif
-//
-//#include <sys/param.h>
-//#include <sys/systm.h>
-//#include <sys/kdb.h>
-//#include <sys/kernel.h>
-//#include <sys/ktr.h>
-//#include <sys/lock.h>
-//#include <sys/mutex.h>
-//#include <sys/proc.h>
-//#include <sys/resource.h>
-//#include <sys/resourcevar.h>
-//#include <sys/sched.h>
-//#include <sys/sdt.h>
-//#include <sys/smp.h>
-//#include <sys/sx.h>
-//#include <sys/sysctl.h>
-//#include <sys/sysproto.h>
-//#include <sys/turnstile.h>
-//#include <sys/umtx.h>
-//#include <sys/vmmeter.h>
-//#include <sys/cpuset.h>
-//#include <sys/sbuf.h>
-//
-//#ifdef HWPMC_HOOKS
-//#include <sys/pmckern.h>
-//#endif
-//
-//#ifdef KDTRACE_HOOKS
-//#include <sys/dtrace_bsd.h>
-//int                          dtrace_vtime_active;
-//dtrace_vtime_switch_func_t   dtrace_vtime_switch_func;
-//#endif
-//
-//#include <machine/cpu.h>
-//#include <machine/smp.h>
-//
-//#if defined(__powerpc__) && defined(E500)
-//#error "This architecture is not currently compatible with ULE"
-//#endif
-//
-//#define      KTR_ULE 0
-//
-//#define      TS_NAME_LEN (MAXCOMLEN + sizeof(" td ") + sizeof(__XSTRING(UINT_MAX)))
-//#define      TDQ_NAME_LEN    (sizeof("sched lock ") + sizeof(__XSTRING(MAXCPU)))
-//#define      TDQ_LOADNAME_LEN        (sizeof("CPU ") + sizeof(__XSTRING(MAXCPU)) - 1 + sizeof(" load"))
-//
-///*
-// * Thread scheduler specific section.  All fields are protected
-// * by the thread lock.
-// */
-//struct td_sched {
-//     struct runq     *ts_runq;       /* Run-queue we're queued on. */
-//     short           ts_flags;       /* TSF_* flags. */
-//     u_char          ts_cpu;         /* CPU that we have affinity for. */
-//     int             ts_rltick;      /* Real last tick, for affinity. */
-//     int             ts_slice;       /* Ticks of slice remaining. */
-//     u_int           ts_slptime;     /* Number of ticks we vol. slept */
-//     u_int           ts_runtime;     /* Number of ticks we were running */
-//     int             ts_ltick;       /* Last tick that we were running on */
-//     int             ts_ftick;       /* First tick that we were running on */
-//     int             ts_ticks;       /* Tick count */
-//#ifdef KTR
-//     char            ts_name[TS_NAME_LEN];
-//#endif
-//};
-///* flags kept in ts_flags */
-//#define      TSF_BOUND       0x0001          /* Thread can not migrate. */
-//#define      TSF_XFERABLE    0x0002          /* Thread was added as transferable. */
-//
-//static struct td_sched td_sched0;
-//
-//#define      THREAD_CAN_MIGRATE(td)  ((td)->td_pinned == 0)
-//#define      THREAD_CAN_SCHED(td, cpu)       \
-//    CPU_ISSET((cpu), &(td)->td_cpuset->cs_mask)
-//
-///*
-// * Priority ranges used for interactive and non-interactive timeshare
-// * threads.  The timeshare priorities are split up into four ranges.
-// * The first range handles interactive threads.  The last three ranges
-// * (NHALF, x, and NHALF) handle non-interactive threads with the outer
-// * ranges supporting nice values.
-// */
-//#define      PRI_TIMESHARE_RANGE     (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE + 1)
-//#define      PRI_INTERACT_RANGE      ((PRI_TIMESHARE_RANGE - SCHED_PRI_NRESV) / 2)
-//#define      PRI_BATCH_RANGE         (PRI_TIMESHARE_RANGE - PRI_INTERACT_RANGE)
-//
-//#define      PRI_MIN_INTERACT        PRI_MIN_TIMESHARE
-//#define      PRI_MAX_INTERACT        (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE - 1)
-//#define      PRI_MIN_BATCH           (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE)
-//#define      PRI_MAX_BATCH           PRI_MAX_TIMESHARE
-//
-///*
-// * Cpu percentage computation macros and defines.
-// *
-// * SCHED_TICK_SECS:  Number of seconds to average the cpu usage across.
-// * SCHED_TICK_TARG:  Number of hz ticks to average the cpu usage across.
-// * SCHED_TICK_MAX:   Maximum number of ticks before scaling back.
-// * SCHED_TICK_SHIFT: Shift factor to avoid rounding away results.
-// * SCHED_TICK_HZ:    Compute the number of hz ticks for a given ticks count.
-// * SCHED_TICK_TOTAL: Gives the amount of time we've been recording ticks.
-// */
-//#define      SCHED_TICK_SECS         10
-//#define      SCHED_TICK_TARG         (hz * SCHED_TICK_SECS)
-//#define      SCHED_TICK_MAX          (SCHED_TICK_TARG + hz)
-//#define      SCHED_TICK_SHIFT        10
-//#define      SCHED_TICK_HZ(ts)       ((ts)->ts_ticks >> SCHED_TICK_SHIFT)
-//#define      SCHED_TICK_TOTAL(ts)    (max((ts)->ts_ltick - (ts)->ts_ftick, hz))
-//
-///*
-// * These macros determine priorities for non-interactive threads.  They are
-// * assigned a priority based on their recent cpu utilization as expressed
-// * by the ratio of ticks to the tick total.  NHALF priorities at the start
-// * and end of the MIN to MAX timeshare range are only reachable with negative
-// * or positive nice respectively.
-// *
-// * PRI_RANGE:        Priority range for utilization dependent priorities.
-// * PRI_NRESV:        Number of nice values.
-// * PRI_TICKS:        Compute a priority in PRI_RANGE from the ticks count and total.
-// * PRI_NICE: Determines the part of the priority inherited from nice.
-// */
-//#define      SCHED_PRI_NRESV         (PRIO_MAX - PRIO_MIN)
-//#define      SCHED_PRI_NHALF         (SCHED_PRI_NRESV / 2)
-//#define      SCHED_PRI_MIN           (PRI_MIN_BATCH + SCHED_PRI_NHALF)
-//#define      SCHED_PRI_MAX           (PRI_MAX_BATCH - SCHED_PRI_NHALF)
-//#define      SCHED_PRI_RANGE         (SCHED_PRI_MAX - SCHED_PRI_MIN + 1)
-//#define      SCHED_PRI_TICKS(ts)                                             \
-//    (SCHED_TICK_HZ((ts)) /                                           \
-//    (roundup(SCHED_TICK_TOTAL((ts)), SCHED_PRI_RANGE) / SCHED_PRI_RANGE))
-//#define      SCHED_PRI_NICE(nice)    (nice)
-//
-///*
-// * These determine the interactivity of a process.  Interactivity differs from
-// * cpu utilization in that it expresses the voluntary time slept vs time ran
-// * while cpu utilization includes all time not running.  This more accurately
-// * models the intent of the thread.
-// *
-// * SLP_RUN_MAX:      Maximum amount of sleep time + run time we'll accumulate
-// *           before throttling back.
-// * SLP_RUN_FORK:     Maximum slp+run time to inherit at fork time.
-// * INTERACT_MAX:     Maximum interactivity value.  Smaller is better.
-// * INTERACT_THRESH:  Threshold for placement on the current runq.
-// */
-//#define      SCHED_SLP_RUN_MAX       ((hz * 5) << SCHED_TICK_SHIFT)
-//#define      SCHED_SLP_RUN_FORK      ((hz / 2) << SCHED_TICK_SHIFT)
-//#define      SCHED_INTERACT_MAX      (100)
-//#define      SCHED_INTERACT_HALF     (SCHED_INTERACT_MAX / 2)
-//#define      SCHED_INTERACT_THRESH   (30)
-//
-///*
-// * tickincr:         Converts a stathz tick into a hz domain scaled by
-// *                   the shift factor.  Without the shift the error rate
-// *                   due to rounding would be unacceptably high.
-// * realstathz:               stathz is sometimes 0 and run off of hz.
-// * sched_slice:              Runtime of each thread before rescheduling.
-// * preempt_thresh:   Priority threshold for preemption and remote IPIs.
-// */
-//static int sched_interact = SCHED_INTERACT_THRESH;
-//static int realstathz;
-//static int tickincr;
-//static int sched_slice = 1;
-//#ifdef PREEMPTION
-//#ifdef FULL_PREEMPTION
-//static int preempt_thresh = PRI_MAX_IDLE;
-//#else
-//static int preempt_thresh = PRI_MIN_KERN;
-//#endif
-//#else
-//static int preempt_thresh = 0;
-//#endif
-//static int static_boost = PRI_MIN_BATCH;
-//static int sched_idlespins = 10000;
-//static int sched_idlespinthresh = -1;
-//
-///*
-// * tdq - per processor runqs and statistics.  All fields are protected by the
-// * tdq_lock.  The load and lowpri may be accessed without to avoid excess
-// * locking in sched_pickcpu();
-// */
-//struct tdq {
-//     /* Ordered to improve efficiency of cpu_search() and switch(). */
-//     struct mtx      tdq_lock;               /* run queue lock. */
-//     struct cpu_group *tdq_cg;               /* Pointer to cpu topology. */
-//     volatile int    tdq_load;               /* Aggregate load. */
-//     volatile int    tdq_cpu_idle;           /* cpu_idle() is active. */
-//     int             tdq_sysload;            /* For loadavg, !ITHD load. */
-//     int             tdq_transferable;       /* Transferable thread count. */
-//     short           tdq_switchcnt;          /* Switches this tick. */
-//     short           tdq_oldswitchcnt;       /* Switches last tick. */
-//     u_char          tdq_lowpri;             /* Lowest priority thread. */
-//     u_char          tdq_ipipending;         /* IPI pending. */
-//     u_char          tdq_idx;                /* Current insert index. */
-//     u_char          tdq_ridx;               /* Current removal index. */
-////   struct runq     tdq_realtime;           /* real-time run queue. */
-//     struct runq     tdq_timeshare;          /* timeshare run queue. */
-//     struct runq     tdq_idle;               /* Queue of IDLE threads. */
-//     char            tdq_name[TDQ_NAME_LEN];
-//#ifdef KTR
-//     char            tdq_loadname[TDQ_LOADNAME_LEN];
-//#endif
-//} __aligned(64);
-//
-///* Idle thread states and config. */
-//#define      TDQ_RUNNING     1
-//#define      TDQ_IDLE        2
-//
-//#ifdef SMP
-//struct cpu_group *cpu_top;           /* CPU topology */
-//
-//#define      SCHED_AFFINITY_DEFAULT  (max(1, hz / 1000))
-//#define      SCHED_AFFINITY(ts, t)   ((ts)->ts_rltick > ticks - ((t) * affinity))
-//
-///*
-// * Run-time tunables.
-// */
-//static int rebalance = 1;
-//static int balance_interval = 128;   /* Default set in sched_initticks(). */
-//static int affinity;
-//static int steal_idle = 1;
-//static int steal_thresh = 2;
-//
-///*
-// * One thread queue per processor.
-// */
-//static struct tdq    tdq_cpu[MAXCPU];
-////static struct tdq  *balance_tdq;
-////static int balance_ticks;
-//static DPCPU_DEFINE(uint32_t, randomval);
-//
-//#define      TDQ_SELF()      (&tdq_cpu[PCPU_GET(cpuid)])
-//#define      TDQ_CPU(x)      (&tdq_cpu[(x)])
-//#define      TDQ_ID(x)       ((int)((x) - tdq_cpu))
-//#else        /* !SMP */
-//static struct tdq    tdq_cpu;
-//
-//#define      TDQ_ID(x)       (0)
-//#define      TDQ_SELF()      (&tdq_cpu)
-//#define      TDQ_CPU(x)      (&tdq_cpu)
-//#endif
-//
-//#define      TDQ_LOCK_ASSERT(t, type)        mtx_assert(TDQ_LOCKPTR((t)), (type))
-//#define      TDQ_LOCK(t)             mtx_lock_spin(TDQ_LOCKPTR((t)))
-//#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)
-//
-////static void sched_priority(struct thread *);
-////static void sched_thread_priority(struct thread *, u_char);
-////static int sched_interact_score(struct thread *);
-////static void sched_interact_update(struct thread *);
-////static void sched_interact_fork(struct thread *);
-////static void sched_pctcpu_update(struct td_sched *, int);
-//
-///* Operations on per processor queues */
-//static struct thread *tdq_choose(struct tdq *);
-//static void tdq_setup(struct tdq *);
-//static void tdq_load_add(struct tdq *, struct thread *);
-//static void tdq_load_rem(struct tdq *, struct thread *);
-//static __inline void tdq_runq_add(struct tdq *, struct thread *, int);
-//static __inline void tdq_runq_rem(struct tdq *, struct thread *);
-//static inline int sched_shouldpreempt(int, int, int);
-//void tdq_print(int cpu);
-//static void runq_print(struct runq *rq);
-//static void tdq_add(struct tdq *, struct thread *, int);
-//#ifdef SMP
-//static int tdq_move(struct tdq *, struct tdq *);
-//static int tdq_idled(struct tdq *);
-//static void tdq_notify(struct tdq *, struct thread *);
-//static struct thread *tdq_steal(struct tdq *, int);
-//static struct thread *runq_steal(struct runq *, int);
-//static int sched_pickcpu(struct thread *, int);
-////static void sched_balance(void);
-////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 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);
-//#endif
-//
-//static void sched_setup(void *dummy);
-//SYSINIT(sched_setup, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, sched_setup, NULL);
-//
-//static void sched_initticks(void *dummy);
-//SYSINIT(sched_initticks, SI_SUB_CLOCKS, SI_ORDER_THIRD, sched_initticks,
-//    NULL);
-//
-//SDT_PROVIDER_DEFINE(sched);
-//
-//SDT_PROBE_DEFINE3(sched, , , change_pri, change-pri, "struct thread *",
-//    "struct proc *", "uint8_t");
-//SDT_PROBE_DEFINE3(sched, , , dequeue, dequeue, "struct thread *",
-//    "struct proc *", "void *");
-//SDT_PROBE_DEFINE4(sched, , , enqueue, enqueue, "struct thread *",
-//    "struct proc *", "void *", "int");
-//SDT_PROBE_DEFINE4(sched, , , lend_pri, lend-pri, "struct thread *",
-//    "struct proc *", "uint8_t", "struct thread *");
-//SDT_PROBE_DEFINE2(sched, , , load_change, load-change, "int", "int");
-//SDT_PROBE_DEFINE2(sched, , , off_cpu, off-cpu, "struct thread *",
-//    "struct proc *");
-//SDT_PROBE_DEFINE(sched, , , on_cpu, on-cpu);
-//SDT_PROBE_DEFINE(sched, , , remain_cpu, remain-cpu);
-//SDT_PROBE_DEFINE2(sched, , , surrender, surrender, "struct thread *",
-//    "struct proc *");
-//
-///*
-// * Print the threads waiting on a run-queue.
-// */
-//static void
-//runq_print(struct runq *rq)
-//{
-//     struct rqhead *rqh;
-//     struct thread *td;
-//     int pri;
-//     int j;
-//     int i;
-//
-//     for (i = 0; i < RQB_LEN; i++) {
-//             printf("\t\trunq bits %d 0x%zx\n",
-//                 i, rq->rq_status.rqb_bits[i]);
-//             for (j = 0; j < RQB_BPW; j++)
-//                     if (rq->rq_status.rqb_bits[i] & (1ul << j)) {
-//                             pri = j + (i << RQB_L2BPW);
-//                             rqh = &rq->rq_queues[pri];
-//                             TAILQ_FOREACH(td, rqh, td_runq) {
-//                                     printf("\t\t\ttd %p(%s) priority %d rqindex %d pri %d\n",
-//                                         td, td->td_name, td->td_priority,
-//                                         td->td_rqindex, pri);
-//                             }
-//                     }
-//     }
-//}
-//
-///*
-// * Print the status of a per-cpu thread queue.  Should be a ddb show cmd.
-// */
-//void
-//tdq_print(int cpu)
-//{
-//     struct tdq *tdq;
-//
-//     tdq = TDQ_CPU(cpu);
-//
-//     printf("tdq %d:\n", TDQ_ID(tdq));
-//     printf("\tlock            %p\n", TDQ_LOCKPTR(tdq));
-//     printf("\tLock name:      %s\n", tdq->tdq_name);
-//     printf("\tload:           %d\n", tdq->tdq_load);
-//     printf("\tswitch cnt:     %d\n", tdq->tdq_switchcnt);
-//     printf("\told switch cnt: %d\n", tdq->tdq_oldswitchcnt);
-//     printf("\ttimeshare idx:  %d\n", tdq->tdq_idx);
-//     printf("\ttimeshare ridx: %d\n", tdq->tdq_ridx);
-//     printf("\tload transferable: %d\n", tdq->tdq_transferable);
-//     printf("\tlowest priority:   %d\n", tdq->tdq_lowpri);
-//     printf("\trealtime runq:\n");
-////   runq_print(&tdq->tdq_realtime);
-//     printf("\ttimeshare runq:\n");
-//     runq_print(&tdq->tdq_timeshare);
-//     printf("\tidle runq:\n");
-//     runq_print(&tdq->tdq_idle);
-//}
-//
-//static inline int
-//sched_shouldpreempt(int pri, int cpri, int remote)
-//{
-//     /*
-//      * If the new priority is not better than the current priority there is
-//      * nothing to do.
-//      */
-////   if (pri >= cpri)
-////           return (0);
-//     /*
-//      * Always preempt idle.
-//      */
-//     if (cpri >= PRI_MIN_IDLE)
-//             return (1);
-//     /*
-//      * If preemption is disabled don't preempt others.
-//      */
-//     if (preempt_thresh == 0)
-//             return (0);
-//     /*
-//      * Preempt if we exceed the threshold.
-//      */
-//     if (pri <= preempt_thresh)
-//             return (1);
-//     /*
-//      * If we're interactive or better and there is non-interactive
-//      * or worse running preempt only remote processors.
-//      */
-//     if (remote && pri <= PRI_MAX_INTERACT && cpri > PRI_MAX_INTERACT)
-//             return (1);
-//     return (0);
-//}
-//
-///*
-// * Add a thread to the actual run-queue.  Keeps transferable counts up to
-// * date with what is actually on the run-queue.  Selects the correct
-// * queue position for timeshare threads.
-// */
-//static __inline void
-//tdq_runq_add(struct tdq *tdq, struct thread *td, int flags)
-//{
-//     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));
-////           /*
-////            * 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 {
-//             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);
-//     }
-//
-//}
-//
-///*
-// * Remove a thread from a run-queue.  This typically happens when a thread
-// * is selected to run.  Running threads are not on the queue and the
-// * transferable count does not reflect them.
-// */
-//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);
-//}
-//
-///*
-// * Load is maintained for all threads RUNNING and ON_RUNQ.  Add the load
-// * for this thread to the referenced thread queue.
-// */
-//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++;
-////   if ((td->td_flags & TDF_NOLOAD) == 0)
-////           tdq->tdq_sysload++;
-////   KTR_COUNTER0(KTR_SCHED, "load", tdq->tdq_loadname, tdq->tdq_load);
-////   SDT_PROBE2(sched, , , load_change, (int)TDQ_ID(tdq), tdq->tdq_load);
-//}
-//
-///*
-// * Remove the load from a thread that is transitioning to a sleep state or
-// * exiting.
-// */
-//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--;
-////   if ((td->td_flags & TDF_NOLOAD) == 0)
-////           tdq->tdq_sysload--;
-////   KTR_COUNTER0(KTR_SCHED, "load", tdq->tdq_loadname, tdq->tdq_load);
-////   SDT_PROBE2(sched, , , load_change, (int)TDQ_ID(tdq), tdq->tdq_load);
-//}
-//
-///*
-// * Set lowpri to its exact value by searching the run-queue and
-// * evaluating curthread.  curthread may be passed as an optimization.
-// */
-////static void
-////tdq_setlowpri(struct tdq *tdq, struct thread *ctd)
-////{
-////   struct thread *td;
-////
-////   TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   if (ctd == NULL)
-////           ctd = pcpu_find(TDQ_ID(tdq))->pc_curthread;
-////   td = tdq_choose(tdq);
-////   if (td == NULL || td->td_priority > ctd->td_priority)
-////           tdq->tdq_lowpri = ctd->td_priority;
-////   else
-////           tdq->tdq_lowpri = td->td_priority;
-////}
-//
-//#ifdef SMP
-//struct cpu_search {
-//     cpuset_t cs_mask;
-//     u_int   cs_prefer;
-//     int     cs_pri;         /* Min priority for low. */
-//     int     cs_limit;       /* Max load for low, min load for high. */
-//     int     cs_cpu;
-//     int     cs_load;
-//};
-//
-//#define      CPU_SEARCH_LOWEST       0x1
-//#define      CPU_SEARCH_HIGHEST      0x2
-//#define      CPU_SEARCH_BOTH         (CPU_SEARCH_LOWEST|CPU_SEARCH_HIGHEST)
-//
-//#define      CPUSET_FOREACH(cpu, mask)                               \
-//     for ((cpu) = 0; (cpu) <= mp_maxid; (cpu)++)             \
-//             if (CPU_ISSET(cpu, &mask))
-//
-//static __inline int cpu_search(const struct cpu_group *cg, struct cpu_search *low,
-//    struct cpu_search *high, const int match);
-//int cpu_search_lowest(const struct cpu_group *cg, struct cpu_search *low);
-//int cpu_search_highest(const struct cpu_group *cg, struct cpu_search *high);
-//int cpu_search_both(const struct cpu_group *cg, struct cpu_search *low,
-//    struct cpu_search *high);
-//
-///*
-// * Search the tree of cpu_groups for the lowest or highest loaded cpu
-// * according to the match argument.  This routine actually compares the
-// * load on all paths through the tree and finds the least loaded cpu on
-// * the least loaded path, which may differ from the least loaded cpu in
-// * the system.  This balances work among caches and busses.
-// *
-// * This inline is instantiated in three forms below using constants for the
-// * match argument.  It is reduced to the minimum set for each case.  It is
-// * also recursive to the depth of the tree.
-// */
-//static __inline int
-//cpu_search(const struct cpu_group *cg, struct cpu_search *low,
-//    struct cpu_search *high, const int match)
-//{
-//     struct cpu_search lgroup;
-//     struct cpu_search hgroup;
-//     cpuset_t cpumask;
-//     struct cpu_group *child;
-//     struct tdq *tdq;
-//     int cpu, i, hload, lload, load, total, rnd, *rndptr;
-//
-//     total = 0;
-//     cpumask = cg->cg_mask;
-//     if (match & CPU_SEARCH_LOWEST) {
-//             lload = INT_MAX;
-//             lgroup = *low;
-//     }
-//     if (match & CPU_SEARCH_HIGHEST) {
-//             hload = INT_MIN;
-//             hgroup = *high;
-//     }
-//
-//     /* Iterate through the child CPU groups and then remaining CPUs. */
-//     for (i = cg->cg_children, cpu = mp_maxid; i >= 0; ) {
-//             if (i == 0) {
-//                     while (cpu >= 0 && !CPU_ISSET(cpu, &cpumask))
-//                             cpu--;
-//                     if (cpu < 0)
-//                             break;
-//                     child = NULL;
-//             } else {
-//                     child = &cg->cg_child[i - 1];
-//             }
-//
-//             if (match & CPU_SEARCH_LOWEST)
-//                     lgroup.cs_cpu = -1;
-//             if (match & CPU_SEARCH_HIGHEST)
-//                     hgroup.cs_cpu = -1;
-//             if (child) {                    /* Handle child CPU group. */
-//                     CPU_NAND(&cpumask, &child->cg_mask);
-//                     switch (match) {
-//                     case CPU_SEARCH_LOWEST:
-//                             load = cpu_search_lowest(child, &lgroup);
-//                             break;
-//                     case CPU_SEARCH_HIGHEST:
-//                             load = cpu_search_highest(child, &hgroup);
-//                             break;
-//                     case CPU_SEARCH_BOTH:
-//                             load = cpu_search_both(child, &lgroup, &hgroup);
-//                             break;
-//                     }
-//             } else {                        /* Handle child CPU. */
-//                     tdq = TDQ_CPU(cpu);
-//                     load = tdq->tdq_load * 256;
-//                     rndptr = DPCPU_PTR(randomval);
-//                     rnd = (*rndptr = *rndptr * 69069 + 5) >> 26;
-//                     if (match & CPU_SEARCH_LOWEST) {
-//                             if (cpu == low->cs_prefer)
-//                                     load -= 64;
-//                             /* If that CPU is allowed and get data. */
-//                             if (tdq->tdq_lowpri > lgroup.cs_pri &&
-//                                 tdq->tdq_load <= lgroup.cs_limit &&
-//                                 CPU_ISSET(cpu, &lgroup.cs_mask)) {
-//                                     lgroup.cs_cpu = cpu;
-//                                     lgroup.cs_load = load - rnd;
-//                             }
-//                     }
-//                     if (match & CPU_SEARCH_HIGHEST) {
-//                             if (tdq->tdq_load >= hgroup.cs_limit &&
-//                                 tdq->tdq_transferable &&
-//                                 CPU_ISSET(cpu, &hgroup.cs_mask)) {
-//                                     hgroup.cs_cpu = cpu;
-//                                     hgroup.cs_load = load - rnd;
-//                             }
-//                     }
-//             }
-//             total += load;
-//
-//             /* We have info about child item. Compare it. */
-//             if (match & CPU_SEARCH_LOWEST) {
-//                     if (lgroup.cs_cpu >= 0 &&
-//                         (load < lload ||
-//                          (load == lload && lgroup.cs_load < low->cs_load))) {
-//                             lload = load;
-//                             low->cs_cpu = lgroup.cs_cpu;
-//                             low->cs_load = lgroup.cs_load;
-//                     }
-//             }
-//             if (match & CPU_SEARCH_HIGHEST)
-//                     if (hgroup.cs_cpu >= 0 &&
-//                         (load > hload ||
-//                          (load == hload && hgroup.cs_load > high->cs_load))) {
-//                             hload = load;
-//                             high->cs_cpu = hgroup.cs_cpu;
-//                             high->cs_load = hgroup.cs_load;
-//                     }
-//             if (child) {
-//                     i--;
-//                     if (i == 0 && CPU_EMPTY(&cpumask))
-//                             break;
-//             } else
-//                     cpu--;
-//     }
-//     return (total);
-//}
-//
-///*
-// * cpu_search instantiations must pass constants to maintain the inline
-// * optimization.
-// */
-//int
-//cpu_search_lowest(const struct cpu_group *cg, struct cpu_search *low)
-//{
-//     return cpu_search(cg, low, NULL, CPU_SEARCH_LOWEST);
-//}
-//
-//int
-//cpu_search_highest(const struct cpu_group *cg, struct cpu_search *high)
-//{
-//     return cpu_search(cg, NULL, high, CPU_SEARCH_HIGHEST);
-//}
-//
-//int
-//cpu_search_both(const struct cpu_group *cg, struct cpu_search *low,
-//    struct cpu_search *high)
-//{
-//     return cpu_search(cg, low, high, CPU_SEARCH_BOTH);
-//}
-//
-///*
-// * Find the cpu with the least load via the least loaded path that has a
-// * lowpri greater than pri  pri.  A pri of -1 indicates any priority is
-// * acceptable.
-// */
-//static inline int
-//sched_lowest(const struct cpu_group *cg, cpuset_t mask, int pri, int maxload,
-//    int prefer)
-//{
-//     struct cpu_search low;
-//
-//     low.cs_cpu = -1;
-//     low.cs_prefer = prefer;
-//     low.cs_mask = mask;
-//     low.cs_pri = pri;
-//     low.cs_limit = maxload;
-//     cpu_search_lowest(cg, &low);
-//     return low.cs_cpu;
-//}
-//
-///*
-// * Find the cpu with the highest load via the highest loaded path.
-// */
-//static inline int
-//sched_highest(const struct cpu_group *cg, cpuset_t mask, int minload)
-//{
-//     struct cpu_search high;
-//
-//     high.cs_cpu = -1;
-//     high.cs_mask = mask;
-//     high.cs_limit = minload;
-//     cpu_search_highest(cg, &high);
-//     return high.cs_cpu;
-//}
-//
-///*
-// * Simultaneously find the highest and lowest loaded cpu reachable via
-// * cg.
-// */
-//static inline void
-//sched_both(const struct cpu_group *cg, cpuset_t mask, int *lowcpu, int *highcpu)
-//{
-//     struct cpu_search high;
-//     struct cpu_search low;
-//
-//     low.cs_cpu = -1;
-//     low.cs_prefer = -1;
-//     low.cs_pri = -1;
-//     low.cs_limit = INT_MAX;
-//     low.cs_mask = mask;
-//     high.cs_cpu = -1;
-//     high.cs_limit = -1;
-//     high.cs_mask = mask;
-//     cpu_search_both(cg, &low, &high);
-//     *lowcpu = low.cs_cpu;
-//     *highcpu = high.cs_cpu;
-//     return;
-//}
-//
-////static void
-////sched_balance_group(struct cpu_group *cg)
-////{
-////   cpuset_t hmask, lmask;
-////   int high, low, anylow;
-////
-////   CPU_FILL(&hmask);
-////   for (;;) {
-////           high = sched_highest(cg, hmask, 1);
-////           /* Stop if there is no more CPU with transferrable threads. */
-////           if (high == -1)
-////                   break;
-////           CPU_CLR(high, &hmask);
-////           CPU_COPY(&hmask, &lmask);
-////           /* Stop if there is no more CPU left for low. */
-////           if (CPU_EMPTY(&lmask))
-////                   break;
-////           anylow = 1;
-////nextlow:
-////           low = sched_lowest(cg, lmask, -1,
-////               TDQ_CPU(high)->tdq_load - 1, high);
-////           /* Stop if we looked well and found no less loaded CPU. */
-////           if (anylow && low == -1)
-////                   break;
-////           /* Go to next high if we found no less loaded CPU. */
-////           if (low == -1)
-////                   continue;
-////           /* Transfer thread from high to low. */
-////           if (sched_balance_pair(TDQ_CPU(high), TDQ_CPU(low))) {
-////                   /* CPU that got thread can no longer be a donor. */
-////                   CPU_CLR(low, &hmask);
-////           } else {
-////                   /*
-////                    * If failed, then there is no threads on high
-////                    * that can run on this low. Drop low from low
-////                    * mask and look for different one.
-////                    */
-////                   CPU_CLR(low, &lmask);
-////                   anylow = 0;
-////                   goto nextlow;
-////           }
-////   }
-////}
-//
-////static void
-////sched_balance(void)
-////{
-////   struct tdq *tdq;
-////
-////   /*
-////    * Select a random time between .5 * balance_interval and
-////    * 1.5 * balance_interval.
-////    */
-////   balance_ticks = max(balance_interval / 2, 1);
-////   balance_ticks += random() % balance_interval;
-////   if (smp_started == 0 || rebalance == 0)
-////           return;
-////   tdq = TDQ_SELF();
-////   TDQ_UNLOCK(tdq);
-////   sched_balance_group(cpu_top);
-////   TDQ_LOCK(tdq);
-////}
-//
-///*
-// * Lock two thread queues using their address to maintain lock order.
-// */
-//static void
-//tdq_lock_pair(struct tdq *one, struct tdq *two)
-//{
-//     if (one < two) {
-//             TDQ_LOCK(one);
-//             TDQ_LOCK_FLAGS(two, MTX_DUPOK);
-//     } else {
-//             TDQ_LOCK(two);
-//             TDQ_LOCK_FLAGS(one, MTX_DUPOK);
-//     }
-//}
-//
-///*
-// * Unlock two thread queues.  Order is not important here.
-// */
-//static void
-//tdq_unlock_pair(struct tdq *one, struct tdq *two)
-//{
-//     TDQ_UNLOCK(one);
-//     TDQ_UNLOCK(two);
-//}
-//
-///*
-// * Transfer load between two imbalanced thread queues.
-// */
-////static int
-////sched_balance_pair(struct tdq *high, struct tdq *low)
-////{
-////   int moved;
-////   int cpu;
-////
-////   tdq_lock_pair(high, low);
-////   moved = 0;
-////   /*
-////    * Determine what the imbalance is and then adjust that to how many
-////    * threads we actually have to give up (transferable).
-////    */
-////   if (high->tdq_transferable != 0 && high->tdq_load > low->tdq_load &&
-////       (moved = tdq_move(high, low)) > 0) {
-////           /*
-////            * In case the target isn't the current cpu IPI it to force a
-////            * reschedule with the new workload.
-////            */
-////           cpu = TDQ_ID(low);
-////           sched_pin();
-////           if (cpu != PCPU_GET(cpuid)) {
-//////                 printf("Sending IPI_PREEMPT3 from %d to %d\n", PCPU_GET(cpuid), cpu);
-////                   ipi_cpu(cpu, IPI_PREEMPT);
-////           }
-////           sched_unpin();
-////   }
-////   tdq_unlock_pair(high, low);
-////   return (moved);
-////}
-//
-///*
-// * Move a thread from one thread queue to another.
-// */
-//static int
-//tdq_move(struct tdq *from, struct tdq *to)
-//{
-//     struct td_sched *ts;
-//     struct thread *td;
-//     struct tdq *tdq;
-//     int cpu;
-//
-//     TDQ_LOCK_ASSERT(from, MA_OWNED);
-//     TDQ_LOCK_ASSERT(to, MA_OWNED);
-//
-//     tdq = from;
-//     cpu = TDQ_ID(to);
-//     td = tdq_steal(tdq, cpu);
-//     if (td == NULL)
-//             return (0);
-//     ts = td->td_sched;
-//     /*
-//      * Although the run queue is locked the thread may be blocked.  Lock
-//      * it to clear this and acquire the run-queue lock.
-//      */
-//     thread_lock(td);
-//     /* Drop recursive lock on from acquired via thread_lock(). */
-//     TDQ_UNLOCK(from);
-//     sched_rem(td);
-//     ts->ts_cpu = cpu;
-//     td->td_lock = TDQ_LOCKPTR(to);
-//     tdq_add(to, td, SRQ_YIELDING);
-//     return (1);
-//}
-//
-///*
-// * This tdq has idled.  Try to steal a thread from another cpu and switch
-// * to it.
-// */
-//static int
-//tdq_idled(struct tdq *tdq)
-//{
-//     struct cpu_group *cg;
-//     struct tdq *steal;
-//     cpuset_t mask;
-//     int thresh;
-//     int cpu;
-//
-//     if (smp_started == 0 || steal_idle == 0)
-//             return (1);
-//     CPU_FILL(&mask);
-//     CPU_CLR(PCPU_GET(cpuid), &mask);
-//     /* We don't want to be preempted while we're iterating. */
-//     spinlock_enter();
-//     for (cg = tdq->tdq_cg; cg != NULL; ) {
-//             if ((cg->cg_flags & CG_FLAG_THREAD) == 0)
-//                     thresh = steal_thresh;
-//             else
-//                     thresh = 1;
-//             cpu = sched_highest(cg, mask, thresh);
-//             if (cpu == -1) {
-//                     cg = cg->cg_parent;
-//                     continue;
-//             }
-//             steal = TDQ_CPU(cpu);
-//             CPU_CLR(cpu, &mask);
-//             tdq_lock_pair(tdq, steal);
-//             if (steal->tdq_load < thresh || steal->tdq_transferable == 0) {
-//                     tdq_unlock_pair(tdq, steal);
-//                     continue;
-//             }
-//             /*
-//              * If a thread was added while interrupts were disabled don't
-//              * steal one here.  If we fail to acquire one due to affinity
-//              * 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;
-//             }
-//             spinlock_exit();
-//             TDQ_UNLOCK(steal);
-//             mi_switch(SW_VOL | SWT_IDLE, NULL);
-//             thread_unlock(curthread);
-//
-//             return (0);
-//     }
-//     spinlock_exit();
-//     return (1);
-//}
-//
-///*
-// * Notify a remote cpu of new work.  Sends an IPI if criteria are met.
-// */
-//static void
-//tdq_notify(struct tdq *tdq, struct thread *td)
-//{
-//     struct thread *ctd;
-//     int pri;
-//     int cpu;
-//
-//     if (tdq->tdq_ipipending)
-//             return;
-//     cpu = td->td_sched->ts_cpu;
-//     pri = td->td_priority;
-//     ctd = pcpu_find(cpu)->pc_curthread;
-//     if (!sched_shouldpreempt(pri, ctd->td_priority, 1))
-//             return;
-//     if (TD_IS_IDLETHREAD(ctd)) {
-//             /*
-//              * If the MD code has an idle wakeup routine try that before
-//              * falling back to IPI.
-//              */
-//             if (!tdq->tdq_cpu_idle || cpu_idle_wakeup(cpu))
-//                     return;
-//     }
-////   printf("Sending IPI_PREEMPT from %d to %d\n", curcpu, cpu);
-//     tdq->tdq_ipipending = 1;
-//     ipi_cpu(cpu, IPI_PREEMPT);
-//}
-//
-///*
-// * Steals load from a timeshare queue.  Honors the rotating queue head
-// * index.
-// */
-//static struct thread *
-//runq_steal_from(struct runq *rq, int cpu, u_char start)
-//{
-//     struct rqbits *rqb;
-//     struct rqhead *rqh;
-//     struct thread *td, *first;
-//     int bit;
-//     int pri;
-//     int i;
-//
-//     rqb = &rq->rq_status;
-//     bit = start & (RQB_BPW -1);
-//     pri = 0;
-//     first = NULL;
-//again:
-//     for (i = RQB_WORD(start); i < RQB_LEN; bit = 0, i++) {
-//             if (rqb->rqb_bits[i] == 0)
-//                     continue;
-//             if (bit != 0) {
-//                     for (pri = bit; pri < RQB_BPW; pri++)
-//                             if (rqb->rqb_bits[i] & (1ul << pri))
-//                                     break;
-//                     if (pri >= RQB_BPW)
-//                             continue;
-//             } else
-//                     pri = RQB_FFS(rqb->rqb_bits[i]);
-//             pri += (i << RQB_L2BPW);
-//             rqh = &rq->rq_queues[pri];
-//             TAILQ_FOREACH(td, rqh, td_runq) {
-//                     if (first && THREAD_CAN_MIGRATE(td) &&
-//                         THREAD_CAN_SCHED(td, cpu))
-//                             return (td);
-//                     first = td;
-//             }
-//     }
-//     if (start != 0) {
-//             start = 0;
-//             goto again;
-//     }
-//
-//     if (first && THREAD_CAN_MIGRATE(first) &&
-//         THREAD_CAN_SCHED(first, cpu))
-//             return (first);
-//     return (NULL);
-//}
-//
-///*
-// * Steals load from a standard linear queue.
-// */
-//static struct thread *
-//runq_steal(struct runq *rq, int cpu)
-//{
-//     struct rqhead *rqh;
-//     struct rqbits *rqb;
-//     struct thread *td;
-//     int word;
-//     int bit;
-//
-//     rqb = &rq->rq_status;
-//     for (word = 0; word < RQB_LEN; word++) {
-//             if (rqb->rqb_bits[word] == 0)
-//                     continue;
-//             for (bit = 0; bit < RQB_BPW; bit++) {
-//                     if ((rqb->rqb_bits[word] & (1ul << bit)) == 0)
-//                             continue;
-//                     rqh = &rq->rq_queues[bit + (word << RQB_L2BPW)];
-//                     TAILQ_FOREACH(td, rqh, td_runq)
-//                             if (THREAD_CAN_MIGRATE(td) &&
-//                                 THREAD_CAN_SCHED(td, cpu))
-//                                     return (td);
-//             }
-//     }
-//     return (NULL);
-//}
-//
-///*
-// * Attempt to steal a thread in priority order from a thread queue.
-// */
-//static struct thread *
-//tdq_steal(struct tdq *tdq, int cpu)
-//{
-//     struct thread *td;
-//
-//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   if ((td = runq_steal(&tdq->tdq_realtime, cpu)) != NULL)
-////           return (td);
-//     if ((td = runq_steal_from(&tdq->tdq_timeshare,
-//         cpu, tdq->tdq_ridx)) != NULL)
-//             return (td);
-//     return (runq_steal(&tdq->tdq_idle, cpu));
-//}
-//
-///*
-// * Sets the thread lock and ts_cpu to match the requested cpu.  Unlocks the
-// * current lock and returns with the assigned queue locked.
-// */
-//static inline struct tdq *
-//sched_setcpu(struct thread *td, int cpu, int flags)
-//{
-//
-//     struct tdq *tdq;
-//
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-//     tdq = TDQ_CPU(cpu);
-//     td->td_sched->ts_cpu = cpu;
-//     /*
-//      * If the lock matches just return the queue.
-//      */
-//     if (td->td_lock == TDQ_LOCKPTR(tdq))
-//             return (tdq);
-//#ifdef notyet
-//     /*
-//      * If the thread isn't running its lockptr is a
-//      * turnstile or a sleepqueue.  We can just lock_set without
-//      * blocking.
-//      */
-//     if (TD_CAN_RUN(td)) {
-//             TDQ_LOCK(tdq);
-//             thread_lock_set(td, TDQ_LOCKPTR(tdq));
-//             return (tdq);
-//     }
-//#endif
-//     /*
-//      * The hard case, migration, we need to block the thread first to
-//      * prevent order reversals with other cpus locks.
-//      */
-//     spinlock_enter();
-//     thread_lock_block(td);
-//     TDQ_LOCK(tdq);
-//     thread_lock_unblock(td, TDQ_LOCKPTR(tdq));
-//     spinlock_exit();
-//     return (tdq);
-//}
-//
-//SCHED_STAT_DEFINE(pickcpu_intrbind, "Soft interrupt binding");
-//SCHED_STAT_DEFINE(pickcpu_idle_affinity, "Picked idle cpu based on affinity");
-//SCHED_STAT_DEFINE(pickcpu_affinity, "Picked cpu based on affinity");
-//SCHED_STAT_DEFINE(pickcpu_lowest, "Selected lowest load");
-//SCHED_STAT_DEFINE(pickcpu_local, "Migrated to current cpu");
-//SCHED_STAT_DEFINE(pickcpu_migration, "Selection may have caused migration");
-//
-//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;
-//
-//     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
-//
-///*
-// * Pick the highest priority task we have and return it.
-// */
-//static struct thread *
-//tdq_choose(struct tdq *tdq)
-//{
-//     struct thread *td;
-//
-//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-////   td = runq_choose(&tdq->tdq_realtime);
-////   if (td != NULL)
-////           return (td);
-//     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);
-//}
-//
-///*
-// * Initialize a thread queue.
-// */
-//static void
-//tdq_setup(struct tdq *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
-//}
-//
-//#ifdef SMP
-//static void
-//sched_setup_smp(void)
-//{
-//     struct tdq *tdq;
-//     int i;
-//
-//     cpu_top = smp_topo();
-//     CPU_FOREACH(i) {
-//             tdq = TDQ_CPU(i);
-//             tdq_setup(tdq);
-//             tdq->tdq_cg = smp_topo_find(cpu_top, i);
-//             if (tdq->tdq_cg == NULL)
-//                     panic("Can't find cpu group for %d\n", i);
-//     }
-////   balance_tdq = TDQ_SELF();
-////   sched_balance();
-//}
-//#endif
-//
-///*
-// * Setup the thread queues and initialize the topology based on MD
-// * information.
-// */
-//static void
-//sched_setup(void *dummy)
-//{
-//     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().
-//      */
-//     realstathz = hz;
-//     sched_slice = (realstathz/10);  /* ~100ms */
-//     tickincr = 1 << SCHED_TICK_SHIFT;
-//
-//     /* Add thread0's load since it's running. */
-//     TDQ_LOCK(tdq);
-//     thread0.td_lock = TDQ_LOCKPTR(TDQ_SELF());
-//     tdq_load_add(tdq, &thread0);
-////   tdq->tdq_lowpri = thread0.td_priority;
-//     TDQ_UNLOCK(tdq);
-//}
-//
-///*
-// * This routine determines the tickincr after stathz and hz are setup.
-// */
-///* ARGSUSED */
-//static void
-//sched_initticks(void *dummy)
-//{
-//     int incr;
-//
-//     realstathz = stathz ? stathz : hz;
-//     sched_slice = (realstathz/10);  /* ~100ms */
-//
-//     /*
-//      * tickincr is shifted out by 10 to avoid rounding errors due to
-//      * hz not being evenly divisible by stathz on all platforms.
-//      */
-//     incr = (hz << SCHED_TICK_SHIFT) / realstathz;
-//     /*
-//      * This does not work for values of stathz that are more than
-//      * 1 << SCHED_TICK_SHIFT * hz.  In practice this does not happen.
-//      */
-//     if (incr == 0)
-//             incr = 1;
-//     tickincr = incr;
-//#ifdef SMP
-//     /*
-//      * Set the default balance interval now that we know
-//      * what realstathz is.
-//      */
-////   balance_interval = realstathz;
-//     /*
-//      * Set steal thresh to roughly log2(mp_ncpu) but no greater than 4.
-//      * This prevents excess thrashing on large machines and excess idle
-//      * on smaller machines.
-//      */
-//     steal_thresh = min(fls(mp_ncpus) - 1, 3);
-//     affinity = SCHED_AFFINITY_DEFAULT;
-//#endif
-//     if (sched_idlespinthresh < 0)
-//             sched_idlespinthresh = max(16, 2 * hz / realstathz);
-//}
-//
-//
-///*
-// * This is the core of the interactivity algorithm.  Determines a score based
-// * on past behavior.  It is the ratio of sleep time to run time scaled to
-// * a [0, 100] integer.  This is the voluntary sleep time of a process, which
-// * differs from the cpu usage because it does not account for time spent
-// * waiting on a run-queue.  Would be prettier if we had floating point.
-// */
-////static int
-////sched_interact_score(struct thread *td)
-////{
-////   struct td_sched *ts;
-////   int div;
-////
-////   ts = td->td_sched;
-////   /*
-////    * The score is only needed if this is likely to be an interactive
-////    * task.  Don't go through the expense of computing it if there's
-////    * no chance.
-////    */
-////   if (sched_interact <= SCHED_INTERACT_HALF &&
-////           ts->ts_runtime >= ts->ts_slptime)
-////                   return (SCHED_INTERACT_HALF);
-////
-////   if (ts->ts_runtime > ts->ts_slptime) {
-////           div = max(1, ts->ts_runtime / SCHED_INTERACT_HALF);
-////           return (SCHED_INTERACT_HALF +
-////               (SCHED_INTERACT_HALF - (ts->ts_slptime / div)));
-////   }
-////   if (ts->ts_slptime > ts->ts_runtime) {
-////           div = max(1, ts->ts_slptime / SCHED_INTERACT_HALF);
-////           return (ts->ts_runtime / div);
-////   }
-////   /* runtime == slptime */
-////   if (ts->ts_runtime)
-////           return (SCHED_INTERACT_HALF);
-////
-////   /*
-////    * This can happen if slptime and runtime are 0.
-////    */
-////   return (0);
-////
-////}
-//
-///*
-// * Scale the scheduling priority according to the "interactivity" of this
-// * process.
-// */
-////static void
-////sched_priority(struct thread *td)
-////{
-////   int score;
-////   int pri;
-////
-////   if (PRI_BASE(td->td_pri_class) != PRI_TIMESHARE)
-////           return;
-////   /*
-////    * If the score is interactive we place the thread in the realtime
-////    * queue with a priority that is less than kernel and interrupt
-////    * priorities.  These threads are not subject to nice restrictions.
-////    *
-////    * Scores greater than this are placed on the normal timeshare queue
-////    * where the priority is partially decided by the most recent cpu
-////    * utilization and the rest is decided by nice value.
-////    *
-////    * The nice value of the process has a linear effect on the calculated
-////    * score.  Negative nice values make it easier for a thread to be
-////    * considered interactive.
-////    */
-////   score = imax(0, sched_interact_score(td) + td->td_proc->p_nice);
-////   if (score < sched_interact) {
-////           pri = PRI_MIN_INTERACT;
-////           pri += ((PRI_MAX_INTERACT - PRI_MIN_INTERACT + 1) /
-////               sched_interact) * score;
-////           KASSERT(pri >= PRI_MIN_INTERACT && pri <= PRI_MAX_INTERACT,
-////               ("sched_priority: invalid interactive priority %d score %d",
-////               pri, score));
-////   } else {
-////           pri = SCHED_PRI_MIN;
-////           if (td->td_sched->ts_ticks)
-////                   pri += min(SCHED_PRI_TICKS(td->td_sched),
-////                       SCHED_PRI_RANGE);
-////           pri += SCHED_PRI_NICE(td->td_proc->p_nice);
-////           KASSERT(pri >= PRI_MIN_BATCH && pri <= PRI_MAX_BATCH,
-////               ("sched_priority: invalid priority %d: nice %d, "
-////               "ticks %d ftick %d ltick %d tick pri %d",
-////               pri, td->td_proc->p_nice, td->td_sched->ts_ticks,
-////               td->td_sched->ts_ftick, td->td_sched->ts_ltick,
-////               SCHED_PRI_TICKS(td->td_sched)));
-////   }
-////   sched_user_prio(td, pri);
-////
-////   return;
-////}
-//
-///*
-// * This routine enforces a maximum limit on the amount of scheduling history
-// * kept.  It is called after either the slptime or runtime is adjusted.  This
-// * function is ugly due to integer math.
-// */
-////static void
-////sched_interact_update(struct thread *td)
-////{
-////   struct td_sched *ts;
-////   u_int sum;
-////
-////   ts = td->td_sched;
-////   sum = ts->ts_runtime + ts->ts_slptime;
-////   if (sum < SCHED_SLP_RUN_MAX)
-////           return;
-////   /*
-////    * This only happens from two places:
-////    * 1) We have added an unusual amount of run time from fork_exit.
-////    * 2) We have added an unusual amount of sleep time from sched_sleep().
-////    */
-////   if (sum > SCHED_SLP_RUN_MAX * 2) {
-////           if (ts->ts_runtime > ts->ts_slptime) {
-////                   ts->ts_runtime = SCHED_SLP_RUN_MAX;
-////                   ts->ts_slptime = 1;
-////           } else {
-////                   ts->ts_slptime = SCHED_SLP_RUN_MAX;
-////                   ts->ts_runtime = 1;
-////           }
-////           return;
-////   }
-////   /*
-////    * If we have exceeded by more than 1/5th then the algorithm below
-////    * will not bring us back into range.  Dividing by two here forces
-////    * us into the range of [4/5 * SCHED_INTERACT_MAX, SCHED_INTERACT_MAX]
-////    */
-////   if (sum > (SCHED_SLP_RUN_MAX / 5) * 6) {
-////           ts->ts_runtime /= 2;
-////           ts->ts_slptime /= 2;
-////           return;
-////   }
-////   ts->ts_runtime = (ts->ts_runtime / 5) * 4;
-////   ts->ts_slptime = (ts->ts_slptime / 5) * 4;
-////}
-//
-///*
-// * Scale back the interactivity history when a child thread is created.  The
-// * history is inherited from the parent but the thread may behave totally
-// * differently.  For example, a shell spawning a compiler process.  We want
-// * to learn that the compiler is behaving badly very quickly.
-// */
-////static void
-////sched_interact_fork(struct thread *td)
-////{
-////   int ratio;
-////   int sum;
-////
-////   sum = td->td_sched->ts_runtime + td->td_sched->ts_slptime;
-////   if (sum > SCHED_SLP_RUN_FORK) {
-////           ratio = sum / SCHED_SLP_RUN_FORK;
-////           td->td_sched->ts_runtime /= ratio;
-////           td->td_sched->ts_slptime /= ratio;
-////   }
-////}
-//
-///*
-// * Called from proc0_init() to setup the scheduler fields.
-// */
-//void
-//schedinit(void)
-//{
-//
-//     /*
-//      * Set up the scheduler specific parts of proc0.
-//      */
-//     proc0.p_sched = NULL; /* XXX */
-//     thread0.td_sched = &td_sched0;
-//     td_sched0.ts_ltick = ticks;
-//     td_sched0.ts_ftick = ticks;
-//     td_sched0.ts_slice = sched_slice;
-//}
-//
-///*
-// * This is only somewhat accurate since given many processes of the same
-// * priority they will switch when their slices run out, which will be
-// * at most sched_slice stathz ticks.
-// */
-//int
-//sched_rr_interval(void)
-//{
-//
-//     /* Convert sched_slice to hz */
-//     return (hz/(realstathz/sched_slice));
-//}
-//
-///*
-// * Update the percent cpu tracking information when it is requested or
-// * the total history exceeds the maximum.  We keep a sliding history of
-// * tick counts that slowly decays.  This is less precise than the 4BSD
-// * mechanism since it happens with less regular and frequent events.
-// */
-////static void
-////sched_pctcpu_update(struct td_sched *ts, int run)
-////{
-////   int t = ticks;
-////
-////   if (t - ts->ts_ltick >= SCHED_TICK_TARG) {
-////           ts->ts_ticks = 0;
-////           ts->ts_ftick = t - SCHED_TICK_TARG;
-////   } else if (t - ts->ts_ftick >= SCHED_TICK_MAX) {
-////           ts->ts_ticks = (ts->ts_ticks / (ts->ts_ltick - ts->ts_ftick)) *
-////               (ts->ts_ltick - (t - SCHED_TICK_TARG));
-////           ts->ts_ftick = t - SCHED_TICK_TARG;
-////   }
-////   if (run)
-////           ts->ts_ticks += (t - ts->ts_ltick) << SCHED_TICK_SHIFT;
-////   ts->ts_ltick = t;
-////}
-//
-///*
-// * Adjust the priority of a thread.  Move it to the appropriate run-queue
-// * if necessary.  This is the back-end for several priority related
-// * functions.
-// */
-////static void
-////sched_thread_priority(struct thread *td, u_char prio)
-////{
-////   struct td_sched *ts;
-////   struct tdq *tdq;
-////   int oldpri;
-////
-////   KTR_POINT3(KTR_SCHED, "thread", sched_tdname(td), "prio",
-////       "prio:%d", td->td_priority, "new prio:%d", prio,
-////       KTR_ATTR_LINKED, sched_tdname(curthread));
-////   SDT_PROBE3(sched, , , change_pri, td, td->td_proc, prio);
-////   if (td != curthread && prio > td->td_priority) {
-////           KTR_POINT3(KTR_SCHED, "thread", sched_tdname(curthread),
-////               "lend prio", "prio:%d", td->td_priority, "new prio:%d",
-////               prio, KTR_ATTR_LINKED, sched_tdname(td));
-////           SDT_PROBE4(sched, , , lend_pri, td, td->td_proc, prio,
-////               curthread);
-////   }
-////   ts = td->td_sched;
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////   if (td->td_priority == prio)
-////           return;
-////   /*
-////    * If the priority has been elevated due to priority
-////    * propagation, we may have to move ourselves to a new
-////    * queue.  This could be optimized to not re-add in some
-////    * cases.
-////    */
-////   if (TD_ON_RUNQ(td) && prio < td->td_priority) {
-////           sched_rem(td);
-////           td->td_priority = prio;
-////           sched_add(td, SRQ_BORROWING);
-////           return;
-////   }
-////   /*
-////    * If the thread is currently running we may have to adjust the lowpri
-////    * information so other cpus are aware of our current priority.
-////    */
-////   if (TD_IS_RUNNING(td)) {
-////           tdq = TDQ_CPU(ts->ts_cpu);
-////           oldpri = td->td_priority;
-////           td->td_priority = prio;
-////           if (prio < tdq->tdq_lowpri)
-////                   tdq->tdq_lowpri = prio;
-////           else if (tdq->tdq_lowpri == oldpri)
-////                   tdq_setlowpri(tdq, td);
-////           return;
-////   }
-////   td->td_priority = prio;
-////}
-//
-///*
-// * Update a thread's priority when it is lent another thread's
-// * priority.
-// */
-//void
-//sched_lend_prio(struct thread *td, u_char prio)
-//{
-////
-////   td->td_flags |= TDF_BORROWING;
-////   sched_thread_priority(td, prio);
-//}
-//
-///*
-// * Restore a thread's priority when priority propagation is
-// * over.  The prio argument is the minimum priority the thread
-// * needs to have to satisfy other possible priority lending
-// * requests.  If the thread's regular priority is less
-// * important than prio, the thread will keep a priority boost
-// * of prio.
-// */
-//void
-//sched_unlend_prio(struct thread *td, u_char prio)
-//{
-////   u_char base_pri;
-////
-////   if (td->td_base_pri >= PRI_MIN_TIMESHARE &&
-////       td->td_base_pri <= PRI_MAX_TIMESHARE)
-////           base_pri = td->td_user_pri;
-////   else
-////           base_pri = td->td_base_pri;
-////   if (prio >= base_pri) {
-////           td->td_flags &= ~TDF_BORROWING;
-////           sched_thread_priority(td, base_pri);
-////   } else
-////           sched_lend_prio(td, prio);
-//}
-//
-///*
-// * Standard entry for setting the priority to an absolute value.
-// */
-//void
-//sched_prio(struct thread *td, u_char prio)
-//{
-//     u_char oldprio;
-////
-////   /* First, update the base priority. */
-////   td->td_base_pri = prio;
-//
-//     oldprio = PVM;
-//
-//     if (TD_IS_IDLETHREAD(td)) {
-//             oldprio = PRI_MAX_IDLE;
-//     }
-//
-//     td->td_base_pri = oldprio;
-//     td->td_priority = oldprio;
-////
-////   /*
-////    * If the thread is borrowing another thread's priority, don't
-////    * ever lower the priority.
-////    */
-////   if (td->td_flags & TDF_BORROWING && td->td_priority < prio)
-////           return;
-////
-////   /* Change the real priority. */
-////   oldprio = td->td_priority;
-////// sched_thread_priority(td, prio);
-////
-////   /*
-////    * If the thread is on a turnstile, then let the turnstile update
-////    * its state.
-////    */
-////   if (TD_ON_LOCK(td) && oldprio != prio)
-////           turnstile_adjust(td, oldprio);
-//}
-//
-///*
-// * Set the base user priority, does not effect current running priority.
-// */
-//void
-//sched_user_prio(struct thread *td, u_char prio)
-//{
-//
-////   td->td_base_user_pri = prio;
-////   if (td->td_lend_user_pri <= prio)
-////           return;
-////   td->td_user_pri = prio;
-//     td->td_base_user_pri = PVM;
-//     td->td_user_pri = PVM;
-//}
-//
-//void
-//sched_lend_user_prio(struct thread *td, u_char prio)
-//{
-//
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////   td->td_lend_user_pri = prio;
-////   td->td_user_pri = min(prio, td->td_base_user_pri);
-////   if (td->td_priority > td->td_user_pri)
-////           sched_prio(td, td->td_user_pri);
-////   else if (td->td_priority != td->td_user_pri)
-////           td->td_flags |= TDF_NEEDRESCHED;
-//}
-//
-///*
-// * 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));
-//}
-//
-///*
-// * Variadic version of thread_lock_unblock() that does not assume td_lock
-// * is blocked.
-// */
-//static inline void
-//thread_unblock_switch(struct thread *td, struct mtx *mtx)
-//{
-//     atomic_store_rel_ptr((volatile uintptr_t *)&td->td_lock,
-//         (uintptr_t)mtx);
-//}
-//
-///*
-// * Switch threads.  This function has to handle threads coming in while
-// * blocked for some reason, running, or idle.  It also must deal with
-// * migrating a thread from one queue to another as running threads may
-// * be assigned elsewhere via binding.
-// */
-//void
-//sched_switch(struct thread *td, struct thread *newtd, int flags)
-//{
-//     struct tdq *tdq;
-//     struct td_sched *ts;
-//     struct mtx *mtx;
-//     int srqflag;
-//     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 {
-//             /* This thread must be going to sleep. */
-//             TDQ_LOCK(tdq);
-//             mtx = thread_lock_block(td);
-//             tdq_load_rem(tdq, td);
-//     }
-//     /*
-//      * 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;
-//}
-//
-///*
-// * Adjust thread priorities as a result of a nice request.
-// */
-//void
-//sched_nice(struct proc *p, int nice)
-//{
-////   struct thread *td;
-////
-////   PROC_LOCK_ASSERT(p, MA_OWNED);
-////
-////   p->p_nice = nice;
-////   FOREACH_THREAD_IN_PROC(p, td) {
-////           thread_lock(td);
-////           sched_priority(td);
-////           sched_prio(td, td->td_base_user_pri);
-////           thread_unlock(td);
-////   }
-//}
-//
-///*
-// * Record the sleep time for the interactivity scorer.
-// */
-//void
-//sched_sleep(struct thread *td, int prio)
-//{
-//
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////
-////   td->td_slptick = ticks;
-////   if (TD_IS_SUSPENDED(td) || prio >= PSOCK)
-////           td->td_flags |= TDF_CANSWAP;
-////   if (PRI_BASE(td->td_pri_class) != PRI_TIMESHARE)
-////           return;
-////   if (static_boost == 1 && prio)
-////           sched_prio(td, prio);
-////   else if (static_boost && td->td_priority > static_boost)
-////           sched_prio(td, static_boost);
-//}
-//
-///*
-// * 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)
-//{
-//     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);
-//}
-//
-///*
-// * Penalize the parent for creating a new child and initialize the child's
-// * priority.
-// */
-//void
-//sched_fork(struct thread *td, struct thread *child)
-//{
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-////   sched_pctcpu_update(td->td_sched, 1);
-//     sched_fork_thread(td, child);
-//     /*
-//      * Penalize the parent and child for forking.
-//      */
-////   sched_interact_fork(child);
-////   sched_priority(child);
-//     td->td_sched->ts_runtime += tickincr;
-////   sched_interact_update(td);
-////   sched_priority(td);
-//}
-//
-///*
-// * Fork a new thread, may be within the same process.
-// */
-//void
-//sched_fork_thread(struct thread *td, struct thread *child)
-//{
-//     struct td_sched *ts;
-//     struct td_sched *ts2;
-//
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-//     /*
-//      * Initialize child.
-//      */
-//     ts = td->td_sched;
-//     ts2 = child->td_sched;
-//     child->td_lock = TDQ_LOCKPTR(TDQ_SELF());
-//     child->td_cpuset = cpuset_ref(td->td_cpuset);
-//     ts2->ts_cpu = ts->ts_cpu;
-//     ts2->ts_flags = 0;
-//     /*
-//      * Grab our parents cpu estimation information.
-//      */
-//     ts2->ts_ticks = ts->ts_ticks;
-//     ts2->ts_ltick = ts->ts_ltick;
-//     ts2->ts_ftick = ts->ts_ftick;
-//     /*
-//      * Do not inherit any borrowed priority from the parent.
-//      */
-//     child->td_priority = child->td_base_pri;
-//     /*
-//      * And update interactivity score.
-//      */
-//     ts2->ts_slptime = ts->ts_slptime;
-//     ts2->ts_runtime = ts->ts_runtime;
-//     ts2->ts_slice = 1;      /* Attempt to quickly learn interactivity. */
-//#ifdef KTR
-//     bzero(ts2->ts_name, sizeof(ts2->ts_name));
-//#endif
-//}
-//
-///*
-// * Adjust the priority class of a thread.
-// */
-//void
-//sched_class(struct thread *td, int class)
-//{
-//
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-//     if (td->td_pri_class == class)
-//             return;
-//     td->td_pri_class = class;
-//}
-//
-///*
-// * Return some of the child's priority and interactivity to the parent.
-// */
-//void
-//sched_exit(struct proc *p, struct thread *child)
-//{
-////   struct thread *td;
-////
-////   KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "proc exit",
-////       "prio:%d", child->td_priority);
-////   PROC_LOCK_ASSERT(p, MA_OWNED);
-////   td = FIRST_THREAD_IN_PROC(p);
-////   sched_exit_thread(td, child);
-//}
-//
-///*
-// * Penalize another thread for the time spent on this one.  This helps to
-// * worsen the priority and interactivity of processes which schedule batch
-// * jobs such as make.  This has little effect on the make process itself but
-// * causes new processes spawned by it to receive worse scores immediately.
-// */
-//void
-//sched_exit_thread(struct thread *td, struct thread *child)
-//{
-//
-////   KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "thread exit",
-////       "prio:%d", child->td_priority);
-////   /*
-////    * Give the child's runtime to the parent without returning the
-////    * sleep time as a penalty to the parent.  This causes shells that
-////    * launch expensive things to mark their children as expensive.
-////    */
-////   thread_lock(td);
-////   td->td_sched->ts_runtime += child->td_sched->ts_runtime;
-////   sched_interact_update(td);
-////   sched_priority(td);
-////   thread_unlock(td);
-//}
-//
-///*
-// * Used by void ipi_bitmap_handler(struct trapframe frame);
-// * sys/amd64/amd64/mp_machdep.c:1267
-// */
-//void
-//sched_preempt(struct thread *td)
-//{
-//     struct tdq *tdq;
-//
-//     SDT_PROBE2(sched, , , surrender, td, td->td_proc);
-//
-//     thread_lock(td);
-//     tdq = TDQ_SELF();
-//     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-//     tdq->tdq_ipipending = 0;
-////   if (td->td_priority > tdq->tdq_lowpri) {
-//             int flags;
-//
-//             flags = SW_INVOL | SW_PREEMPT;
-//             if (td->td_critnest > 1)
-//                     td->td_owepreempt = 1;
-//             else if (TD_IS_IDLETHREAD(td))
-//                     mi_switch(flags | SWT_REMOTEWAKEIDLE, NULL);
-//             else
-//                     mi_switch(flags | SWT_REMOTEPREEMPT, NULL);
-////   }
-//     thread_unlock(td);
-//}
-//
-///*
-// * Fix priorities on return to user-space.  Priorities may be elevated due
-// * to static priorities in msleep() or similar.
-// */
-//void
-//sched_userret(struct thread *td)
-//{
-////   /*
-////    * XXX we cheat slightly on the locking here to avoid locking in
-////    * the usual case.  Setting td_priority here is essentially an
-////    * incomplete workaround for not setting it properly elsewhere.
-////    * Now that some interrupt handlers are threads, not setting it
-////    * properly elsewhere can clobber it in the window between setting
-////    * it here and returning to user mode, so don't waste time setting
-////    * it perfectly here.
-////    */
-////   KASSERT((td->td_flags & TDF_BORROWING) == 0,
-////       ("thread with borrowed priority returning to userland"));
-////   if (td->td_priority != td->td_user_pri) {
-////           thread_lock(td);
-////           td->td_priority = td->td_user_pri;
-////           td->td_base_pri = td->td_user_pri;
-////           tdq_setlowpri(TDQ_SELF(), td);
-////           thread_unlock(td);
-////    }
-//}
-//
-///*
-// * Handle a stathz tick.  This is really only relevant for timeshare
-// * threads.
-// */
-//void
-//sched_clock(struct thread *td)
-//{
-//     struct tdq *tdq;
-//     struct td_sched *ts;
-//
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-//     tdq = TDQ_SELF();
-//#ifdef SMP
-//     /*
-//      * We run the long term load balancer infrequently on the first cpu.
-//      */
-////   if (balance_tdq == tdq) {
-////           if (balance_ticks && --balance_ticks == 0)
-////                   sched_balance();
-////   }
-//#endif
-//     /*
-//      * Save the old switch count so we have a record of the last ticks
-//      * activity.   Initialize the new switch count based on our load.
-//      * If there is some activity seed it to reflect that.
-//      */
-//     tdq->tdq_oldswitchcnt = tdq->tdq_switchcnt;
-//     tdq->tdq_switchcnt = tdq->tdq_load;
-//     /*
-//      * Advance the insert index once for each tick to ensure that all
-//      * threads get a chance to run.
-//      */
-//     if (tdq->tdq_idx == tdq->tdq_ridx) {
-//             tdq->tdq_idx = (tdq->tdq_idx + 1) % RQ_NQS;
-//             if (TAILQ_EMPTY(&tdq->tdq_timeshare.rq_queues[tdq->tdq_ridx]))
-//                     tdq->tdq_ridx = tdq->tdq_idx;
-//     }
-//     ts = td->td_sched;
-////   sched_pctcpu_update(ts, 1);
-//     if (td->td_pri_class & PRI_FIFO_BIT)
-//             return;
-//     if (PRI_BASE(td->td_pri_class) == PRI_TIMESHARE) {
+/*-
+ * Copyright (c) 2002-2007, Jeffrey Roberson <jeff@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file implements the ULE scheduler.  ULE supports independent CPU
+ * run queues and fine grain locking.  It has superior interactive
+ * performance under load even on uni-processor systems.
+ *
+ * etymology:
+ *   ULE is the last three letters in schedule.  It owes its name to a
+ * generic user created for a scheduling system by Paul Mikesell at
+ * Isilon Systems and a general lack of creativity on the part of the author.
+ */
+
+/*
+ * TODO:
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
+#include "opt_sched.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/smp.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/turnstile.h>
+#include <sys/umtx.h>
+#include <sys/vmmeter.h>
+#include <sys/cpuset.h>
+#include <sys/sbuf.h>
+
+#ifdef HWPMC_HOOKS
+#include <sys/pmckern.h>
+#endif
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+int                            dtrace_vtime_active;
+dtrace_vtime_switch_func_t     dtrace_vtime_switch_func;
+#endif
+
+#include <machine/cpu.h>
+#include <machine/smp.h>
+
+#if defined(__powerpc__) && defined(E500)
+#error "This architecture is not currently compatible with ULE"
+#endif
+
+#define        KTR_ULE 0
+
+#define        TS_NAME_LEN (MAXCOMLEN + sizeof(" td ") + sizeof(__XSTRING(UINT_MAX)))
+#define        TDQ_NAME_LEN    (sizeof("sched lock ") + sizeof(__XSTRING(MAXCPU)))
+#define        TDQ_LOADNAME_LEN        (sizeof("CPU ") + sizeof(__XSTRING(MAXCPU)) - 1 + sizeof(" load"))
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
+#include "opt_sched.h"
+
+#ifdef FW_MOD_SCHED
+#include "fw.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/smp.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/turnstile.h>
+#include <sys/umtx.h>
+#include <sys/vmmeter.h>
+#include <sys/cpuset.h>
+#include <sys/sbuf.h>
+
+#ifdef HWPMC_HOOKS
+#include <sys/pmckern.h>
+#endif
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+int                            dtrace_vtime_active;
+dtrace_vtime_switch_func_t     dtrace_vtime_switch_func;
+#endif
+
+#include <machine/cpu.h>
+#include <machine/smp.h>
+
+#if defined(__powerpc__) && defined(E500)
+#error "This architecture is not currently compatible with ULE"
+#endif
+
+#define        KTR_ULE 0
+
+#define        TS_NAME_LEN (MAXCOMLEN + sizeof(" td ") + sizeof(__XSTRING(UINT_MAX)))
+#define        TDQ_NAME_LEN    (sizeof("sched lock ") + sizeof(__XSTRING(MAXCPU)))
+#define        TDQ_LOADNAME_LEN        (sizeof("CPU ") + sizeof(__XSTRING(MAXCPU)) - 1 + sizeof(" load"))
+
+/*
+ * Thread scheduler specific section.  All fields are protected
+ * by the thread lock.
+ */
+struct td_sched {
+       struct runq     *ts_runq;       /* Run-queue we're queued on. */
+       short           ts_flags;       /* TSF_* flags. */
+       u_char          ts_cpu;         /* CPU that we have affinity for. */
+       int             ts_rltick;      /* Real last tick, for affinity. */
+       int             ts_slice;       /* Ticks of slice remaining. */
+       u_int           ts_slptime;     /* Number of ticks we vol. slept */
+       u_int           ts_runtime;     /* Number of ticks we were running */
+       int             ts_ltick;       /* Last tick that we were running on */
+       int             ts_ftick;       /* First tick that we were running on */
+       int             ts_ticks;       /* Tick count */
+#ifdef KTR
+       char            ts_name[TS_NAME_LEN];
+#endif
+};
+/* flags kept in ts_flags */
+#define        TSF_BOUND       0x0001          /* Thread can not migrate. */
+#define        TSF_XFERABLE    0x0002          /* Thread was added as transferable. */
+
+static struct td_sched td_sched0;
+
+#define        THREAD_CAN_MIGRATE(td)  ((td)->td_pinned == 0)
+#define        THREAD_CAN_SCHED(td, cpu)       \
+struct td_sched {
+       struct runq     *ts_runq;       /* Run-queue we're queued on. */
+       short           ts_flags;       /* TSF_* flags. */
+       u_char          ts_cpu;         /* CPU that we have affinity for. */
+       int             ts_rltick;      /* Real last tick, for affinity. */
+       int             ts_slice;       /* Ticks of slice remaining. */
+       u_int           ts_slptime;     /* Number of ticks we vol. slept */
+       u_int           ts_runtime;     /* Number of ticks we were running */
+       int             ts_ltick;       /* Last tick that we were running on */
+       int             ts_ftick;       /* First tick that we were running on */
+       int             ts_ticks;       /* Tick count */
+#ifdef KTR
+       char            ts_name[TS_NAME_LEN];
+#endif
+};
+/* flags kept in ts_flags */
+#define        TSF_BOUND       0x0001          /* Thread can not migrate. */
+#define        TSF_XFERABLE    0x0002          /* Thread was added as transferable. */
+
+static struct td_sched td_sched0;
+
+#define        THREAD_CAN_MIGRATE(td)  ((td)->td_pinned == 0)
+#define        THREAD_CAN_SCHED(td, cpu)       \
+    CPU_ISSET((cpu), &(td)->td_cpuset->cs_mask)
+
+/*
+ * Priority ranges used for interactive and non-interactive timeshare
+ * threads.  The timeshare priorities are split up into four ranges.
+ * The first range handles interactive threads.  The last three ranges
+ * (NHALF, x, and NHALF) handle non-interactive threads with the outer
+ * ranges supporting nice values.
+ */
+#define        PRI_TIMESHARE_RANGE     (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE + 1)
+#define        PRI_INTERACT_RANGE      ((PRI_TIMESHARE_RANGE - SCHED_PRI_NRESV) / 2)
+#define        PRI_BATCH_RANGE         (PRI_TIMESHARE_RANGE - PRI_INTERACT_RANGE)
+
+#define        PRI_MIN_INTERACT        PRI_MIN_TIMESHARE
+#define        PRI_MAX_INTERACT        (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE - 1)
+#define        PRI_MIN_BATCH           (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE)
+#define        PRI_MAX_BATCH           PRI_MAX_TIMESHARE
+
+/*
+ * Cpu percentage computation macros and defines.
+ *
+ * SCHED_TICK_SECS:    Number of seconds to average the cpu usage across.
+ * SCHED_TICK_TARG:    Number of hz ticks to average the cpu usage across.
+ * SCHED_TICK_MAX:     Maximum number of ticks before scaling back.
+ * SCHED_TICK_SHIFT:   Shift factor to avoid rounding away results.
+ * SCHED_TICK_HZ:      Compute the number of hz ticks for a given ticks count.
+ * SCHED_TICK_TOTAL:   Gives the amount of time we've been recording ticks.
+ */
+#define        SCHED_TICK_SECS         10
+#define        SCHED_TICK_TARG         (hz * SCHED_TICK_SECS)
+#define        SCHED_TICK_MAX          (SCHED_TICK_TARG + hz)
+#define        SCHED_TICK_SHIFT        10
+#define        SCHED_TICK_HZ(ts)       ((ts)->ts_ticks >> SCHED_TICK_SHIFT)
+#define        SCHED_TICK_TOTAL(ts)    (max((ts)->ts_ltick - (ts)->ts_ftick, hz))
+
+/*
+ * These macros determine priorities for non-interactive threads.  They are
+ * assigned a priority based on their recent cpu utilization as expressed
+ * by the ratio of ticks to the tick total.  NHALF priorities at the start
+ * and end of the MIN to MAX timeshare range are only reachable with negative
+ * or positive nice respectively.
+ *
+ * PRI_RANGE:  Priority range for utilization dependent priorities.
+ * PRI_NRESV:  Number of nice values.
+ * PRI_TICKS:  Compute a priority in PRI_RANGE from the ticks count and total.
+ * PRI_NICE:   Determines the part of the priority inherited from nice.
+ */
+#define        SCHED_PRI_NRESV         (PRIO_MAX - PRIO_MIN)
+#define        SCHED_PRI_NHALF         (SCHED_PRI_NRESV / 2)
+#define        SCHED_PRI_MIN           (PRI_MIN_BATCH + SCHED_PRI_NHALF)
+#define        SCHED_PRI_MAX           (PRI_MAX_BATCH - SCHED_PRI_NHALF)
+#define        SCHED_PRI_RANGE         (SCHED_PRI_MAX - SCHED_PRI_MIN + 1)
+#define        SCHED_PRI_TICKS(ts)                                             \
+    (SCHED_TICK_HZ((ts)) /                                             \
+    (roundup(SCHED_TICK_TOTAL((ts)), SCHED_PRI_RANGE) / SCHED_PRI_RANGE))
+#define        SCHED_PRI_NICE(nice)    (nice)
+
+/*
+ * These determine the interactivity of a process.  Interactivity differs from
+ * cpu utilization in that it expresses the voluntary time slept vs time ran
+ * while cpu utilization includes all time not running.  This more accurately
+ * models the intent of the thread.
+ *
+ * SLP_RUN_MAX:        Maximum amount of sleep time + run time we'll accumulate
+ *             before throttling back.
+ * SLP_RUN_FORK:       Maximum slp+run time to inherit at fork time.
+ * INTERACT_MAX:       Maximum interactivity value.  Smaller is better.
+ * INTERACT_THRESH:    Threshold for placement on the current runq.
+ */
+#define        SCHED_SLP_RUN_MAX       ((hz * 5) << SCHED_TICK_SHIFT)
+#define        SCHED_SLP_RUN_FORK      ((hz / 2) << SCHED_TICK_SHIFT)
+#define        SCHED_INTERACT_MAX      (100)
+#define        SCHED_INTERACT_HALF     (SCHED_INTERACT_MAX / 2)
+#define        SCHED_INTERACT_THRESH   (30)
+
+/*
+ * tickincr:           Converts a stathz tick into a hz domain scaled by
+ *                     the shift factor.  Without the shift the error rate
+ *                     due to rounding would be unacceptably high.
+ * realstathz:         stathz is sometimes 0 and run off of hz.
+ * sched_slice:                Runtime of each thread before rescheduling.
+ * preempt_thresh:     Priority threshold for preemption and remote IPIs.
+ */
+static int sched_interact = SCHED_INTERACT_THRESH;
+static int realstathz;
+static int tickincr;
+static int sched_slice = 1;
+#ifdef PREEMPTION
+#ifdef FULL_PREEMPTION
+static int preempt_thresh = PRI_MAX_IDLE;
+#else
+static int preempt_thresh = PRI_MIN_KERN;
+#endif
+#else
+static int preempt_thresh = 0;
+#endif
+static int static_boost = PRI_MIN_BATCH;
+static int sched_idlespins = 10000;
+static int sched_idlespinthresh = -1;
+
+/*
+ * tdq - per processor runqs and statistics.  All fields are protected by the
+ * tdq_lock.  The load and lowpri may be accessed without to avoid excess
+ * locking in sched_pickcpu();
+ */
+struct tdq {
+       /* Ordered to improve efficiency of cpu_search() and switch(). */
+       struct mtx      tdq_lock;               /* run queue lock. */
+       struct cpu_group *tdq_cg;               /* Pointer to cpu topology. */
+       volatile int    tdq_load;               /* Aggregate load. */
+       volatile int    tdq_cpu_idle;           /* cpu_idle() is active. */
+       int             tdq_sysload;            /* For loadavg, !ITHD load. */
+       int             tdq_transferable;       /* Transferable thread count. */
+       short           tdq_switchcnt;          /* Switches this tick. */
+       short           tdq_oldswitchcnt;       /* Switches last tick. */
+       u_char          tdq_lowpri;             /* Lowest priority thread. */
+       u_char          tdq_ipipending;         /* IPI pending. */
+       u_char          tdq_idx;                /* Current insert index. */
+       u_char          tdq_ridx;               /* Current removal index. */
+//     struct runq     tdq_realtime;           /* real-time run queue. */
+       struct runq     tdq_timeshare;          /* timeshare run queue. */
+       struct runq     tdq_idle;               /* Queue of IDLE threads. */
+       char            tdq_name[TDQ_NAME_LEN];
+#ifdef KTR
+       char            tdq_loadname[TDQ_LOADNAME_LEN];
+#endif
+} __aligned(64);
+
+/* Idle thread states and config. */
+#define        TDQ_RUNNING     1
+#define        TDQ_IDLE        2
+
+#ifdef SMP
+struct cpu_group *cpu_top;             /* CPU topology */
+
+#define        SCHED_AFFINITY_DEFAULT  (max(1, hz / 1000))
+#define        SCHED_AFFINITY(ts, t)   ((ts)->ts_rltick > ticks - ((t) * affinity))
+
+/*
+ * Run-time tunables.
+ */
+static int rebalance = 1;
+static int balance_interval = 128;     /* Default set in sched_initticks(). */
+static int affinity;
+static int steal_idle = 1;
+static int steal_thresh = 2;
+
+/*
+ * One thread queue per processor.
+ */
+static struct tdq      tdq_cpu[MAXCPU];
+//static struct tdq    *balance_tdq;
+//static int balance_ticks;
+static DPCPU_DEFINE(uint32_t, randomval);
+
+#define        TDQ_SELF()      (&tdq_cpu[PCPU_GET(cpuid)])
+#define        TDQ_CPU(x)      (&tdq_cpu[(x)])
+#define        TDQ_ID(x)       ((int)((x) - tdq_cpu))
+#else  /* !SMP */
+static struct tdq      tdq_cpu;
+
+#define        TDQ_ID(x)       (0)
+#define        TDQ_SELF()      (&tdq_cpu)
+#define        TDQ_CPU(x)      (&tdq_cpu)
+#endif
+
+#define        TDQ_LOCK_ASSERT(t, type)        mtx_assert(TDQ_LOCKPTR((t)), (type))
+#define        TDQ_LOCK(t)             mtx_lock_spin(TDQ_LOCKPTR((t)))
+#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)
+
+//static void sched_priority(struct thread *);
+//static void sched_thread_priority(struct thread *, u_char);
+//static int sched_interact_score(struct thread *);
+//static void sched_interact_update(struct thread *);
+//static void sched_interact_fork(struct thread *);
+//static void sched_pctcpu_update(struct td_sched *, int);
+
+/* Operations on per processor queues */
+static struct thread *tdq_choose(struct tdq *);
+static void tdq_setup(struct tdq *);
+static void tdq_load_add(struct tdq *, struct thread *);
+static void tdq_load_rem(struct tdq *, struct thread *);
+static __inline void tdq_runq_add(struct tdq *, struct thread *, int);
+static __inline void tdq_runq_rem(struct tdq *, struct thread *);
+static inline int sched_shouldpreempt(int, int, int);
+void tdq_print(int cpu);
+static void runq_print(struct runq *rq);
+static void tdq_add(struct tdq *, struct thread *, int);
+#ifdef SMP
+static int tdq_move(struct tdq *, struct tdq *);
+static int tdq_idled(struct tdq *);
+static void tdq_notify(struct tdq *, struct thread *);
+static struct thread *tdq_steal(struct tdq *, int);
+static struct thread *runq_steal(struct runq *, int);
+static int sched_pickcpu(struct thread *, int);
+//static void sched_balance(void);
+//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 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);
+#endif
+
+static void sched_setup(void *dummy);
+SYSINIT(sched_setup, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, sched_setup, NULL);
+
+static void sched_initticks(void *dummy);
+SYSINIT(sched_initticks, SI_SUB_CLOCKS, SI_ORDER_THIRD, sched_initticks,
+    NULL);
+
+SDT_PROVIDER_DEFINE(sched);
+
+SDT_PROBE_DEFINE3(sched, , , change_pri, change-pri, "struct thread *",
+    "struct proc *", "uint8_t");
+SDT_PROBE_DEFINE3(sched, , , dequeue, dequeue, "struct thread *",
+    "struct proc *", "void *");
+SDT_PROBE_DEFINE4(sched, , , enqueue, enqueue, "struct thread *",
+    "struct proc *", "void *", "int");
+SDT_PROBE_DEFINE4(sched, , , lend_pri, lend-pri, "struct thread *",
+    "struct proc *", "uint8_t", "struct thread *");
+SDT_PROBE_DEFINE2(sched, , , load_change, load-change, "int", "int");
+SDT_PROBE_DEFINE2(sched, , , off_cpu, off-cpu, "struct thread *",
+    "struct proc *");
+SDT_PROBE_DEFINE(sched, , , on_cpu, on-cpu);
+SDT_PROBE_DEFINE(sched, , , remain_cpu, remain-cpu);
+SDT_PROBE_DEFINE2(sched, , , surrender, surrender, "struct thread *",
+    "struct proc *");
+
+/*
+ * Print the threads waiting on a run-queue.
+ */
+static void
+runq_print(struct runq *rq)
+{
+       struct rqhead *rqh;
+       struct thread *td;
+       int pri;
+       int j;
+       int i;
+
+       for (i = 0; i < RQB_LEN; i++) {
+               printf("\t\trunq bits %d 0x%zx\n",
+                   i, rq->rq_status.rqb_bits[i]);
+               for (j = 0; j < RQB_BPW; j++)
+                       if (rq->rq_status.rqb_bits[i] & (1ul << j)) {
+                               pri = j + (i << RQB_L2BPW);
+                               rqh = &rq->rq_queues[pri];
+                               TAILQ_FOREACH(td, rqh, td_runq) {
+                                       printf("\t\t\ttd %p(%s) priority %d rqindex %d pri %d\n",
+                                           td, td->td_name, td->td_priority,
+                                           td->td_rqindex, pri);
+                               }
+                       }
+       }
+}
+
+/*
+ * Print the status of a per-cpu thread queue.  Should be a ddb show cmd.
+ */
+void
+tdq_print(int cpu)
+{
+       struct tdq *tdq;
+
+       tdq = TDQ_CPU(cpu);
+
+       printf("tdq %d:\n", TDQ_ID(tdq));
+       printf("\tlock            %p\n", TDQ_LOCKPTR(tdq));
+       printf("\tLock name:      %s\n", tdq->tdq_name);
+       printf("\tload:           %d\n", tdq->tdq_load);
+       printf("\tswitch cnt:     %d\n", tdq->tdq_switchcnt);
+       printf("\told switch cnt: %d\n", tdq->tdq_oldswitchcnt);
+       printf("\ttimeshare idx:  %d\n", tdq->tdq_idx);
+       printf("\ttimeshare ridx: %d\n", tdq->tdq_ridx);
+       printf("\tload transferable: %d\n", tdq->tdq_transferable);
+       printf("\tlowest priority:   %d\n", tdq->tdq_lowpri);
+       printf("\trealtime runq:\n");
+//     runq_print(&tdq->tdq_realtime);
+       printf("\ttimeshare runq:\n");
+       runq_print(&tdq->tdq_timeshare);
+       printf("\tidle runq:\n");
+       runq_print(&tdq->tdq_idle);
+}
+
+static inline int
+sched_shouldpreempt(int pri, int cpri, int remote)
+{
+       /*
+        * If the new priority is not better than the current priority there is
+        * nothing to do.
+        */
+//     if (pri >= cpri)
+//             return (0);
+       /*
+        * Always preempt idle.
+        */
+       if (cpri >= PRI_MIN_IDLE)
+               return (1);
+       /*
+        * If preemption is disabled don't preempt others.
+        */
+       if (preempt_thresh == 0)
+               return (0);
+       /*
+        * Preempt if we exceed the threshold.
+        */
+       if (pri <= preempt_thresh)
+               return (1);
+       /*
+        * If we're interactive or better and there is non-interactive
+        * or worse running preempt only remote processors.
+        */
+       if (remote && pri <= PRI_MAX_INTERACT && cpri > PRI_MAX_INTERACT)
+               return (1);
+       return (0);
+}
+
+/*
+ * Add a thread to the actual run-queue.  Keeps transferable counts up to
+ * date with what is actually on the run-queue.  Selects the correct
+ * queue position for timeshare threads.
+ */
+static __inline void
+tdq_runq_add(struct tdq *tdq, struct thread *td, int flags)
+{
+       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));
 //             /*
-//              * We used a tick; charge it to the thread so
-//              * that we can compute our interactivity.
+//              * This queue contains only priorities between MIN and MAX
+//              * realtime.  Use the whole queue to represent these values.
 //              */
-//             td->td_sched->ts_runtime += tickincr;
-////           sched_interact_update(td);
-////           sched_priority(td);
-//     }
-//     /*
-//      * We used up one time slice.
-//      */
-//     if (--ts->ts_slice > 0)
+//             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;
-//     /*
-//      * We're out of time, force a requeue at userret().
-//      */
-//     ts->ts_slice = sched_slice;
-//     td->td_flags |= TDF_NEEDRESCHED;
-//}
-//
-///*
-// * Called once per hz tick.
-// */
-//void
-//sched_tick(int cnt)
-//{
-//
-//}
-//
-///*
-// * Return whether the current CPU has runnable tasks.  Used for in-kernel
-// * cooperative idle threads.
-// */
-//int
-//sched_runnable(void)
-//{
-//     struct tdq *tdq;
-//     int load;
-//
-//     load = 1;
-//
-//     tdq = TDQ_SELF();
-//     if ((curthread->td_flags & TDF_IDLETD) != 0) {
-//             if (tdq->tdq_load > 0)
-//                     goto out;
 //     } else
-//             if (tdq->tdq_load - 1 > 0)
-//                     goto out;
-//     load = 0;
-//out:
-//     return (load);
-//}
-//
-///*
-// * Choose the highest priority thread to run.  The thread is removed from
-// * the run-queue while running however the load remains.  For SMP we set
-// * the tdq in the global idle bitmask if it idles here.
-// */
-//struct thread *
-//sched_choose(void)
+//             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);
+       }
+
+}
+
+/*
+ * Remove a thread from a run-queue.  This typically happens when a thread
+ * is selected to run.  Running threads are not on the queue and the
+ * transferable count does not reflect them.
+ */
+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);
+}
+
+/*
+ * Load is maintained for all threads RUNNING and ON_RUNQ.  Add the load
+ * for this thread to the referenced thread queue.
+ */
+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++;
+//     if ((td->td_flags & TDF_NOLOAD) == 0)
+//             tdq->tdq_sysload++;
+//     KTR_COUNTER0(KTR_SCHED, "load", tdq->tdq_loadname, tdq->tdq_load);
+//     SDT_PROBE2(sched, , , load_change, (int)TDQ_ID(tdq), tdq->tdq_load);
+}
+
+/*
+ * Remove the load from a thread that is transitioning to a sleep state or
+ * exiting.
+ */
+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--;
+//     if ((td->td_flags & TDF_NOLOAD) == 0)
+//             tdq->tdq_sysload--;
+//     KTR_COUNTER0(KTR_SCHED, "load", tdq->tdq_loadname, tdq->tdq_load);
+//     SDT_PROBE2(sched, , , load_change, (int)TDQ_ID(tdq), tdq->tdq_load);
+}
+
+/*
+ * Set lowpri to its exact value by searching the run-queue and
+ * evaluating curthread.  curthread may be passed as an optimization.
+ */
+//static void
+//tdq_setlowpri(struct tdq *tdq, struct thread *ctd)
 //{
 //     struct thread *td;
-//     struct tdq *tdq;
 //
-//     tdq = TDQ_SELF();
 //     TDQ_LOCK_ASSERT(tdq, MA_OWNED);
-//
+//     if (ctd == NULL)
+//             ctd = pcpu_find(TDQ_ID(tdq))->pc_curthread;
 //     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
-//sched_setpreempt(struct thread *td)
-//{
-//     struct thread *ctd;
-//     int cpri;
-//     int pri;
-//
-//     THREAD_LOCK_ASSERT(curthread, MA_OWNED);
-//
-//     ctd = curthread;
-//     pri = td->td_priority;
-//     cpri = ctd->td_priority;
-//     if (pri < cpri)
-//             ctd->td_flags |= TDF_NEEDRESCHED;
-//     if (panicstr != NULL || pri >= cpri || cold || TD_IS_INHIBITED(ctd))
-//             return;
-//     if (!sched_shouldpreempt(pri, cpri, 0))
-//             return;
-//     ctd->td_owepreempt = 1;
-//}
-//
-///*
-// * Add a thread to a thread queue.  Select the appropriate runq and add the
-// * thread to it.  This is the internal function called when the tdq is
-// * predetermined.
-// */
-//void
-//tdq_add(struct tdq *tdq, struct thread *td, int flags)
+//     if (td == NULL || td->td_priority > ctd->td_priority)
+//             tdq->tdq_lowpri = ctd->td_priority;
+//     else
+//             tdq->tdq_lowpri = td->td_priority;
+//}
+
+#ifdef SMP
+struct cpu_search {
+       cpuset_t cs_mask;
+       u_int   cs_prefer;
+       int     cs_pri;         /* Min priority for low. */
+       int     cs_limit;       /* Max load for low, min load for high. */
+       int     cs_cpu;
+       int     cs_load;
+};
+
+#define        CPU_SEARCH_LOWEST       0x1
+#define        CPU_SEARCH_HIGHEST      0x2
+#define        CPU_SEARCH_BOTH         (CPU_SEARCH_LOWEST|CPU_SEARCH_HIGHEST)
+
+#define        CPUSET_FOREACH(cpu, mask)                               \
+       for ((cpu) = 0; (cpu) <= mp_maxid; (cpu)++)             \
+               if (CPU_ISSET(cpu, &mask))
+
+static __inline int cpu_search(const struct cpu_group *cg, struct cpu_search *low,
+    struct cpu_search *high, const int match);
+int cpu_search_lowest(const struct cpu_group *cg, struct cpu_search *low);
+int cpu_search_highest(const struct cpu_group *cg, struct cpu_search *high);
+int cpu_search_both(const struct cpu_group *cg, struct cpu_search *low,
+    struct cpu_search *high);
+
+/*
+ * Search the tree of cpu_groups for the lowest or highest loaded cpu
+ * according to the match argument.  This routine actually compares the
+ * load on all paths through the tree and finds the least loaded cpu on
+ * the least loaded path, which may differ from the least loaded cpu in
+ * the system.  This balances work among caches and busses.
+ *
+ * This inline is instantiated in three forms below using constants for the
+ * match argument.  It is reduced to the minimum set for each case.  It is
+ * also recursive to the depth of the tree.
+ */
+static __inline int
+cpu_search(const struct cpu_group *cg, struct cpu_search *low,
+    struct cpu_search *high, const int match)
+{
+       struct cpu_search lgroup;
+       struct cpu_search hgroup;
+       cpuset_t cpumask;
+       struct cpu_group *child;
+       struct tdq *tdq;
+       int cpu, i, hload, lload, load, total, rnd, *rndptr;
+
+       total = 0;
+       cpumask = cg->cg_mask;
+       if (match & CPU_SEARCH_LOWEST) {
+               lload = INT_MAX;
+               lgroup = *low;
+       }
+       if (match & CPU_SEARCH_HIGHEST) {
+               hload = INT_MIN;
+               hgroup = *high;
+       }
+
+       /* Iterate through the child CPU groups and then remaining CPUs. */
+       for (i = cg->cg_children, cpu = mp_maxid; i >= 0; ) {
+               if (i == 0) {
+                       while (cpu >= 0 && !CPU_ISSET(cpu, &cpumask))
+                               cpu--;
+                       if (cpu < 0)
+                               break;
+                       child = NULL;
+               } else {
+                       child = &cg->cg_child[i - 1];
+               }
+
+               if (match & CPU_SEARCH_LOWEST)
+                       lgroup.cs_cpu = -1;
+               if (match & CPU_SEARCH_HIGHEST)
+                       hgroup.cs_cpu = -1;
+               if (child) {                    /* Handle child CPU group. */
+                       CPU_NAND(&cpumask, &child->cg_mask);
+                       switch (match) {
+                       case CPU_SEARCH_LOWEST:
+                               load = cpu_search_lowest(child, &lgroup);
+                               break;
+                       case CPU_SEARCH_HIGHEST:
+                               load = cpu_search_highest(child, &hgroup);
+                               break;
+                       case CPU_SEARCH_BOTH:
+                               load = cpu_search_both(child, &lgroup, &hgroup);
+                               break;
+                       }
+               } else {                        /* Handle child CPU. */
+                       tdq = TDQ_CPU(cpu);
+                       load = tdq->tdq_load * 256;
+                       rndptr = DPCPU_PTR(randomval);
+                       rnd = (*rndptr = *rndptr * 69069 + 5) >> 26;
+                       if (match & CPU_SEARCH_LOWEST) {
+                               if (cpu == low->cs_prefer)
+                                       load -= 64;
+                               /* If that CPU is allowed and get data. */
+                               if (tdq->tdq_lowpri > lgroup.cs_pri &&
+                                   tdq->tdq_load <= lgroup.cs_limit &&
+                                   CPU_ISSET(cpu, &lgroup.cs_mask)) {
+                                       lgroup.cs_cpu = cpu;
+                                       lgroup.cs_load = load - rnd;
+                               }
+                       }
+                       if (match & CPU_SEARCH_HIGHEST) {
+                               if (tdq->tdq_load >= hgroup.cs_limit &&
+                                   tdq->tdq_transferable &&
+                                   CPU_ISSET(cpu, &hgroup.cs_mask)) {
+                                       hgroup.cs_cpu = cpu;
+                                       hgroup.cs_load = load - rnd;
+                               }
+                       }
+               }
+               total += load;
+
+               /* We have info about child item. Compare it. */
+               if (match & CPU_SEARCH_LOWEST) {
+                       if (lgroup.cs_cpu >= 0 &&
+                           (load < lload ||
+                            (load == lload && lgroup.cs_load < low->cs_load))) {
+                               lload = load;
+                               low->cs_cpu = lgroup.cs_cpu;
+                               low->cs_load = lgroup.cs_load;
+                       }
+               }
+               if (match & CPU_SEARCH_HIGHEST)
+                       if (hgroup.cs_cpu >= 0 &&
+                           (load > hload ||
+                            (load == hload && hgroup.cs_load > high->cs_load))) {
+                               hload = load;
+                               high->cs_cpu = hgroup.cs_cpu;
+                               high->cs_load = hgroup.cs_load;
+                       }
+               if (child) {
+                       i--;
+                       if (i == 0 && CPU_EMPTY(&cpumask))
+                               break;
+               } else
+                       cpu--;
+       }
+       return (total);
+}
+
+/*
+ * cpu_search instantiations must pass constants to maintain the inline
+ * optimization.
+ */
+int
+cpu_search_lowest(const struct cpu_group *cg, struct cpu_search *low)
+{
+       return cpu_search(cg, low, NULL, CPU_SEARCH_LOWEST);
+}
+
+int
+cpu_search_highest(const struct cpu_group *cg, struct cpu_search *high)
+{
+       return cpu_search(cg, NULL, high, CPU_SEARCH_HIGHEST);
+}
+
+int
+cpu_search_both(const struct cpu_group *cg, struct cpu_search *low,
+    struct cpu_search *high)
+{
+       return cpu_search(cg, low, high, CPU_SEARCH_BOTH);
+}
+
+/*
+ * Find the cpu with the least load via the least loaded path that has a
+ * lowpri greater than pri  pri.  A pri of -1 indicates any priority is
+ * acceptable.
+ */
+static inline int
+sched_lowest(const struct cpu_group *cg, cpuset_t mask, int pri, int maxload,
+    int prefer)
+{
+       struct cpu_search low;
+
+       low.cs_cpu = -1;
+       low.cs_prefer = prefer;
+       low.cs_mask = mask;
+       low.cs_pri = pri;
+       low.cs_limit = maxload;
+       cpu_search_lowest(cg, &low);
+       return low.cs_cpu;
+}
+
+/*
+ * Find the cpu with the highest load via the highest loaded path.
+ */
+static inline int
+sched_highest(const struct cpu_group *cg, cpuset_t mask, int minload)
+{
+       struct cpu_search high;
+
+       high.cs_cpu = -1;
+       high.cs_mask = mask;
+       high.cs_limit = minload;
+       cpu_search_highest(cg, &high);
+       return high.cs_cpu;
+}
+
+/*
+ * Simultaneously find the highest and lowest loaded cpu reachable via
+ * cg.
+ */
+static inline void
+sched_both(const struct cpu_group *cg, cpuset_t mask, int *lowcpu, int *highcpu)
+{
+       struct cpu_search high;
+       struct cpu_search low;
+
+       low.cs_cpu = -1;
+       low.cs_prefer = -1;
+       low.cs_pri = -1;
+       low.cs_limit = INT_MAX;
+       low.cs_mask = mask;
+       high.cs_cpu = -1;
+       high.cs_limit = -1;
+       high.cs_mask = mask;
+       cpu_search_both(cg, &low, &high);
+       *lowcpu = low.cs_cpu;
+       *highcpu = high.cs_cpu;
+       return;
+}
+
+//static void
+//sched_balance_group(struct cpu_group *cg)
 //{
+//     cpuset_t hmask, lmask;
+//     int high, low, anylow;
 //
-//     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);
+//     CPU_FILL(&hmask);
+//     for (;;) {
+//             high = sched_highest(cg, hmask, 1);
+//             /* Stop if there is no more CPU with transferrable threads. */
+//             if (high == -1)
+//                     break;
+//             CPU_CLR(high, &hmask);
+//             CPU_COPY(&hmask, &lmask);
+//             /* Stop if there is no more CPU left for low. */
+//             if (CPU_EMPTY(&lmask))
+//                     break;
+//             anylow = 1;
+//nextlow:
+//             low = sched_lowest(cg, lmask, -1,
+//                 TDQ_CPU(high)->tdq_load - 1, high);
+//             /* Stop if we looked well and found no less loaded CPU. */
+//             if (anylow && low == -1)
+//                     break;
+//             /* Go to next high if we found no less loaded CPU. */
+//             if (low == -1)
+//                     continue;
+//             /* Transfer thread from high to low. */
+//             if (sched_balance_pair(TDQ_CPU(high), TDQ_CPU(low))) {
+//                     /* CPU that got thread can no longer be a donor. */
+//                     CPU_CLR(low, &hmask);
+//             } else {
+//                     /*
+//                      * If failed, then there is no threads on high
+//                      * that can run on this low. Drop low from low
+//                      * mask and look for different one.
+//                      */
+//                     CPU_CLR(low, &lmask);
+//                     anylow = 0;
+//                     goto nextlow;
+//             }
+//     }
 //}
-//
-///*
-// * Select the target thread queue and add a thread to it.  Request
-// * preemption or IPI a remote processor if required.
-// */
-//void
-//sched_add(struct thread *td, int flags)
+
+//static void
+//sched_balance(void)
 //{
 //     struct tdq *tdq;
-//#ifdef SMP
-//     int cpu;
-//#endif
 //
-////   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.
+//      * Select a random time between .5 * balance_interval and
+//      * 1.5 * balance_interval.
 //      */
-//     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);
+//     balance_ticks = max(balance_interval / 2, 1);
+//     balance_ticks += random() % balance_interval;
+//     if (smp_started == 0 || rebalance == 0)
 //             return;
-//     }
-//#else
 //     tdq = TDQ_SELF();
+//     TDQ_UNLOCK(tdq);
+//     sched_balance_group(cpu_top);
 //     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);
 //}
-//
-///*
-// * Remove a thread from a run-queue without running it.  This is used
-// * when we're stealing a thread from a remote queue.  Otherwise all threads
-// * exit by calling sched_exit_thread() and sched_throw() themselves.
-// */
-//void
-//sched_rem(struct thread *td)
+
+/*
+ * Lock two thread queues using their address to maintain lock order.
+ */
+static void
+tdq_lock_pair(struct tdq *one, struct tdq *two)
+{
+       if (one < two) {
+               TDQ_LOCK(one);
+               TDQ_LOCK_FLAGS(two, MTX_DUPOK);
+       } else {
+               TDQ_LOCK(two);
+               TDQ_LOCK_FLAGS(one, MTX_DUPOK);
+       }
+}
+
+/*
+ * Unlock two thread queues.  Order is not important here.
+ */
+static void
+tdq_unlock_pair(struct tdq *one, struct tdq *two)
+{
+       TDQ_UNLOCK(one);
+       TDQ_UNLOCK(two);
+}
+
+/*
+ * Transfer load between two imbalanced thread queues.
+ */
+//static int
+//sched_balance_pair(struct tdq *high, struct tdq *low)
 //{
-//     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_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);
-//}
+//     int moved;
+//     int cpu;
 //
-///*
-// * Fetch cpu utilization information.  Updates on demand.
-// */
-//fixpt_t
-//sched_pctcpu(struct thread *td)
+//     tdq_lock_pair(high, low);
+//     moved = 0;
+//     /*
+//      * Determine what the imbalance is and then adjust that to how many
+//      * threads we actually have to give up (transferable).
+//      */
+//     if (high->tdq_transferable != 0 && high->tdq_load > low->tdq_load &&
+//         (moved = tdq_move(high, low)) > 0) {
+//             /*
+//              * In case the target isn't the current cpu IPI it to force a
+//              * reschedule with the new workload.
+//              */
+//             cpu = TDQ_ID(low);
+//             sched_pin();
+//             if (cpu != PCPU_GET(cpuid)) {
+////                   printf("Sending IPI_PREEMPT3 from %d to %d\n", PCPU_GET(cpuid), cpu);
+//                     ipi_cpu(cpu, IPI_PREEMPT);
+//             }
+//             sched_unpin();
+//     }
+//     tdq_unlock_pair(high, low);
+//     return (moved);
+//}
+
+/*
+ * Move a thread from one thread queue to another.
+ */
+static int
+tdq_move(struct tdq *from, struct tdq *to)
+{
+       struct td_sched *ts;
+       struct thread *td;
+       struct tdq *tdq;
+       int cpu;
+
+       TDQ_LOCK_ASSERT(from, MA_OWNED);
+       TDQ_LOCK_ASSERT(to, MA_OWNED);
+
+       tdq = from;
+       cpu = TDQ_ID(to);
+       td = tdq_steal(tdq, cpu);
+       if (td == NULL)
+               return (0);
+       ts = td->td_sched;
+       /*
+        * Although the run queue is locked the thread may be blocked.  Lock
+        * it to clear this and acquire the run-queue lock.
+        */
+       thread_lock(td);
+       /* Drop recursive lock on from acquired via thread_lock(). */
+       TDQ_UNLOCK(from);
+       sched_rem(td);
+       ts->ts_cpu = cpu;
+       td->td_lock = TDQ_LOCKPTR(to);
+       tdq_add(to, td, SRQ_YIELDING);
+       return (1);
+}
+
+/*
+ * This tdq has idled.  Try to steal a thread from another cpu and switch
+ * to it.
+ */
+static int
+tdq_idled(struct tdq *tdq)
+{
+       struct cpu_group *cg;
+       struct tdq *steal;
+       cpuset_t mask;
+       int thresh;
+       int cpu;
+
+       if (smp_started == 0 || steal_idle == 0)
+               return (1);
+       CPU_FILL(&mask);
+       CPU_CLR(PCPU_GET(cpuid), &mask);
+       /* We don't want to be preempted while we're iterating. */
+       spinlock_enter();
+       for (cg = tdq->tdq_cg; cg != NULL; ) {
+               if ((cg->cg_flags & CG_FLAG_THREAD) == 0)
+                       thresh = steal_thresh;
+               else
+                       thresh = 1;
+               cpu = sched_highest(cg, mask, thresh);
+               if (cpu == -1) {
+                       cg = cg->cg_parent;
+                       continue;
+               }
+               steal = TDQ_CPU(cpu);
+               CPU_CLR(cpu, &mask);
+               tdq_lock_pair(tdq, steal);
+               if (steal->tdq_load < thresh || steal->tdq_transferable == 0) {
+                       tdq_unlock_pair(tdq, steal);
+                       continue;
+               }
+               /*
+                * If a thread was added while interrupts were disabled don't
+                * steal one here.  If we fail to acquire one due to affinity
+                * 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;
+               }
+               spinlock_exit();
+               TDQ_UNLOCK(steal);
+               mi_switch(SW_VOL | SWT_IDLE, NULL);
+               thread_unlock(curthread);
+
+               return (0);
+       }
+       spinlock_exit();
+       return (1);
+}
+
+/*
+ * Notify a remote cpu of new work.  Sends an IPI if criteria are met.
+ */
+static void
+tdq_notify(struct tdq *tdq, struct thread *td)
+{
+       struct thread *ctd;
+       int pri;
+       int cpu;
+
+       if (tdq->tdq_ipipending)
+               return;
+       cpu = td->td_sched->ts_cpu;
+       pri = td->td_priority;
+       ctd = pcpu_find(cpu)->pc_curthread;
+       if (!sched_shouldpreempt(pri, ctd->td_priority, 1))
+               return;
+       if (TD_IS_IDLETHREAD(ctd)) {
+               /*
+                * If the MD code has an idle wakeup routine try that before
+                * falling back to IPI.
+                */
+               if (!tdq->tdq_cpu_idle || cpu_idle_wakeup(cpu))
+                       return;
+       }
+//     printf("Sending IPI_PREEMPT from %d to %d\n", curcpu, cpu);
+       tdq->tdq_ipipending = 1;
+       ipi_cpu(cpu, IPI_PREEMPT);
+}
+
+/*
+ * Steals load from a timeshare queue.  Honors the rotating queue head
+ * index.
+ */
+static struct thread *
+runq_steal_from(struct runq *rq, int cpu, u_char start)
+{
+       struct rqbits *rqb;
+       struct rqhead *rqh;
+       struct thread *td, *first;
+       int bit;
+       int pri;
+       int i;
+
+       rqb = &rq->rq_status;
+       bit = start & (RQB_BPW -1);
+       pri = 0;
+       first = NULL;
+again:
+       for (i = RQB_WORD(start); i < RQB_LEN; bit = 0, i++) {
+               if (rqb->rqb_bits[i] == 0)
+                       continue;
+               if (bit != 0) {
+                       for (pri = bit; pri < RQB_BPW; pri++)
+                               if (rqb->rqb_bits[i] & (1ul << pri))
+                                       break;
+                       if (pri >= RQB_BPW)
+                               continue;
+               } else
+                       pri = RQB_FFS(rqb->rqb_bits[i]);
+               pri += (i << RQB_L2BPW);
+               rqh = &rq->rq_queues[pri];
+               TAILQ_FOREACH(td, rqh, td_runq) {
+                       if (first && THREAD_CAN_MIGRATE(td) &&
+                           THREAD_CAN_SCHED(td, cpu))
+                               return (td);
+                       first = td;
+               }
+       }
+       if (start != 0) {
+               start = 0;
+               goto again;
+       }
+
+       if (first && THREAD_CAN_MIGRATE(first) &&
+           THREAD_CAN_SCHED(first, cpu))
+               return (first);
+       return (NULL);
+}
+
+/*
+ * Steals load from a standard linear queue.
+ */
+static struct thread *
+runq_steal(struct runq *rq, int cpu)
+{
+       struct rqhead *rqh;
+       struct rqbits *rqb;
+       struct thread *td;
+       int word;
+       int bit;
+
+       rqb = &rq->rq_status;
+       for (word = 0; word < RQB_LEN; word++) {
+               if (rqb->rqb_bits[word] == 0)
+                       continue;
+               for (bit = 0; bit < RQB_BPW; bit++) {
+                       if ((rqb->rqb_bits[word] & (1ul << bit)) == 0)
+                               continue;
+                       rqh = &rq->rq_queues[bit + (word << RQB_L2BPW)];
+                       TAILQ_FOREACH(td, rqh, td_runq)
+                               if (THREAD_CAN_MIGRATE(td) &&
+                                   THREAD_CAN_SCHED(td, cpu))
+                                       return (td);
+               }
+       }
+       return (NULL);
+}
+
+/*
+ * Attempt to steal a thread in priority order from a thread queue.
+ */
+static struct thread *
+tdq_steal(struct tdq *tdq, int cpu)
+{
+       struct thread *td;
+
+       TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     if ((td = runq_steal(&tdq->tdq_realtime, cpu)) != NULL)
+//             return (td);
+       if ((td = runq_steal_from(&tdq->tdq_timeshare,
+           cpu, tdq->tdq_ridx)) != NULL)
+               return (td);
+       return (runq_steal(&tdq->tdq_idle, cpu));
+}
+
+/*
+ * Sets the thread lock and ts_cpu to match the requested cpu.  Unlocks the
+ * current lock and returns with the assigned queue locked.
+ */
+static inline struct tdq *
+sched_setcpu(struct thread *td, int cpu, int flags)
+{
+
+       struct tdq *tdq;
+
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+       tdq = TDQ_CPU(cpu);
+       td->td_sched->ts_cpu = cpu;
+       /*
+        * If the lock matches just return the queue.
+        */
+       if (td->td_lock == TDQ_LOCKPTR(tdq))
+               return (tdq);
+#ifdef notyet
+       /*
+        * If the thread isn't running its lockptr is a
+        * turnstile or a sleepqueue.  We can just lock_set without
+        * blocking.
+        */
+       if (TD_CAN_RUN(td)) {
+               TDQ_LOCK(tdq);
+               thread_lock_set(td, TDQ_LOCKPTR(tdq));
+               return (tdq);
+       }
+#endif
+       /*
+        * The hard case, migration, we need to block the thread first to
+        * prevent order reversals with other cpus locks.
+        */
+       spinlock_enter();
+       thread_lock_block(td);
+       TDQ_LOCK(tdq);
+       thread_lock_unblock(td, TDQ_LOCKPTR(tdq));
+       spinlock_exit();
+       return (tdq);
+}
+
+SCHED_STAT_DEFINE(pickcpu_intrbind, "Soft interrupt binding");
+SCHED_STAT_DEFINE(pickcpu_idle_affinity, "Picked idle cpu based on affinity");
+SCHED_STAT_DEFINE(pickcpu_affinity, "Picked cpu based on affinity");
+SCHED_STAT_DEFINE(pickcpu_lowest, "Selected lowest load");
+SCHED_STAT_DEFINE(pickcpu_local, "Migrated to current cpu");
+SCHED_STAT_DEFINE(pickcpu_migration, "Selection may have caused migration");
+
+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;
+
+       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
+
+/*
+ * Pick the highest priority task we have and return it.
+ */
+static struct thread *
+tdq_choose(struct tdq *tdq)
+{
+       struct thread *td;
+
+       TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+//     td = runq_choose(&tdq->tdq_realtime);
+//     if (td != NULL)
+//             return (td);
+       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);
+}
+
+/*
+ * Initialize a thread queue.
+ */
+static void
+tdq_setup(struct tdq *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
+}
+
+#ifdef SMP
+static void
+sched_setup_smp(void)
+{
+       struct tdq *tdq;
+       int i;
+
+       cpu_top = smp_topo();
+       CPU_FOREACH(i) {
+               tdq = TDQ_CPU(i);
+               tdq_setup(tdq);
+               tdq->tdq_cg = smp_topo_find(cpu_top, i);
+               if (tdq->tdq_cg == NULL)
+                       panic("Can't find cpu group for %d\n", i);
+       }
+//     balance_tdq = TDQ_SELF();
+//     sched_balance();
+}
+#endif
+
+/*
+ * Setup the thread queues and initialize the topology based on MD
+ * information.
+ */
+static void
+sched_setup(void *dummy)
+{
+       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().
+        */
+       realstathz = hz;
+       sched_slice = (realstathz/10);  /* ~100ms */
+       tickincr = 1 << SCHED_TICK_SHIFT;
+
+       /* Add thread0's load since it's running. */
+       TDQ_LOCK(tdq);
+       thread0.td_lock = TDQ_LOCKPTR(TDQ_SELF());
+       tdq_load_add(tdq, &thread0);
+//     tdq->tdq_lowpri = thread0.td_priority;
+       TDQ_UNLOCK(tdq);
+}
+
+/*
+ * This routine determines the tickincr after stathz and hz are setup.
+ */
+/* ARGSUSED */
+static void
+sched_initticks(void *dummy)
+{
+       int incr;
+
+       realstathz = stathz ? stathz : hz;
+       sched_slice = (realstathz/10);  /* ~100ms */
+
+       /*
+        * tickincr is shifted out by 10 to avoid rounding errors due to
+        * hz not being evenly divisible by stathz on all platforms.
+        */
+       incr = (hz << SCHED_TICK_SHIFT) / realstathz;
+       /*
+        * This does not work for values of stathz that are more than
+        * 1 << SCHED_TICK_SHIFT * hz.  In practice this does not happen.
+        */
+       if (incr == 0)
+               incr = 1;
+       tickincr = incr;
+#ifdef SMP
+       /*
+        * Set the default balance interval now that we know
+        * what realstathz is.
+        */
+//     balance_interval = realstathz;
+       /*
+        * Set steal thresh to roughly log2(mp_ncpu) but no greater than 4.
+        * This prevents excess thrashing on large machines and excess idle
+        * on smaller machines.
+        */
+       steal_thresh = min(fls(mp_ncpus) - 1, 3);
+       affinity = SCHED_AFFINITY_DEFAULT;
+#endif
+       if (sched_idlespinthresh < 0)
+               sched_idlespinthresh = max(16, 2 * hz / realstathz);
+}
+
+
+/*
+ * This is the core of the interactivity algorithm.  Determines a score based
+ * on past behavior.  It is the ratio of sleep time to run time scaled to
+ * a [0, 100] integer.  This is the voluntary sleep time of a process, which
+ * differs from the cpu usage because it does not account for time spent
+ * waiting on a run-queue.  Would be prettier if we had floating point.
+ */
+//static int
+//sched_interact_score(struct thread *td)
 //{
-//     fixpt_t pctcpu;
 //     struct td_sched *ts;
+//     int div;
 //
-//     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;
-////
-////           /* How many rtick per second ? */
-////           rtick = min(SCHED_TICK_HZ(ts) / SCHED_TICK_SECS, hz);
-////           pctcpu = (FSCALE * ((FSCALE * rtick)/hz)) >> FSHIFT;
-////   }
+//     /*
+//      * The score is only needed if this is likely to be an interactive
+//      * task.  Don't go through the expense of computing it if there's
+//      * no chance.
+//      */
+//     if (sched_interact <= SCHED_INTERACT_HALF &&
+//             ts->ts_runtime >= ts->ts_slptime)
+//                     return (SCHED_INTERACT_HALF);
+//
+//     if (ts->ts_runtime > ts->ts_slptime) {
+//             div = max(1, ts->ts_runtime / SCHED_INTERACT_HALF);
+//             return (SCHED_INTERACT_HALF +
+//                 (SCHED_INTERACT_HALF - (ts->ts_slptime / div)));
+//     }
+//     if (ts->ts_slptime > ts->ts_runtime) {
+//             div = max(1, ts->ts_slptime / SCHED_INTERACT_HALF);
+//             return (ts->ts_runtime / div);
+//     }
+//     /* runtime == slptime */
+//     if (ts->ts_runtime)
+//             return (SCHED_INTERACT_HALF);
 //
-//     return (pctcpu);
-//}
+//     /*
+//      * This can happen if slptime and runtime are 0.
+//      */
+//     return (0);
 //
-///*
-// * Enforce affinity settings for a thread.  Called after adjustments to
-// * cpumask.
-// */
-//void
-//sched_affinity(struct thread *td)
-//{
-////#ifdef SMP
-////   struct td_sched *ts;
-////
-////   THREAD_LOCK_ASSERT(td, MA_OWNED);
-////   ts = td->td_sched;
-////   if (THREAD_CAN_SCHED(td, ts->ts_cpu))
-////           return;
-////   if (TD_ON_RUNQ(td)) {
-////           sched_rem(td);
-////           sched_add(td, SRQ_BORING);
-////           return;
-////   }
-////   if (!TD_IS_RUNNING(td))
-////           return;
-////   /*
-////    * Force a switch before returning to userspace.  If the
-////    * target thread is not running locally send an ipi to force
-////    * the issue.
-////    */
-////   td->td_flags |= TDF_NEEDRESCHED;
-////   if (td != curthread) {
-//////         printf("Sending IPI_PREEMPT2 from %d to %d\n", curcpu, ts->ts_cpu);
-////           ipi_cpu(ts->ts_cpu, IPI_PREEMPT);
-////   }
-////#endif
 //}
-//
-///*
-// * Bind a thread to a target cpu.
-// */
-//void
-//sched_bind(struct thread *td, int cpu)
+
+/*
+ * Scale the scheduling priority according to the "interactivity" of this
+ * process.
+ */
+//static void
+//sched_priority(struct thread *td)
 //{
-//     struct td_sched *ts;
+//     int score;
+//     int pri;
 //
-//     THREAD_LOCK_ASSERT(td, MA_OWNED|MA_NOTRECURSED);
-//     KASSERT(td == curthread, ("sched_bind: can only bind curthread"));
-//     ts = td->td_sched;
-//     if (ts->ts_flags & TSF_BOUND)
-//             sched_unbind(td);
-//     KASSERT(THREAD_CAN_MIGRATE(td), ("%p must be migratable", td));
-//     ts->ts_flags |= TSF_BOUND;
-//     sched_pin();
-//     if (PCPU_GET(cpuid) == cpu)
+//     if (PRI_BASE(td->td_pri_class) != PRI_TIMESHARE)
 //             return;
-//     ts->ts_cpu = cpu;
-//     /* When we return from mi_switch we'll be on the correct cpu. */
-//     mi_switch(SW_VOL, NULL);
-//}
+//     /*
+//      * If the score is interactive we place the thread in the realtime
+//      * queue with a priority that is less than kernel and interrupt
+//      * priorities.  These threads are not subject to nice restrictions.
+//      *
+//      * Scores greater than this are placed on the normal timeshare queue
+//      * where the priority is partially decided by the most recent cpu
+//      * utilization and the rest is decided by nice value.
+//      *
+//      * The nice value of the process has a linear effect on the calculated
+//      * score.  Negative nice values make it easier for a thread to be
+//      * considered interactive.
+//      */
+//     score = imax(0, sched_interact_score(td) + td->td_proc->p_nice);
+//     if (score < sched_interact) {
+//             pri = PRI_MIN_INTERACT;
+//             pri += ((PRI_MAX_INTERACT - PRI_MIN_INTERACT + 1) /
+//                 sched_interact) * score;
+//             KASSERT(pri >= PRI_MIN_INTERACT && pri <= PRI_MAX_INTERACT,
+//                 ("sched_priority: invalid interactive priority %d score %d",
+//                 pri, score));
+//     } else {
+//             pri = SCHED_PRI_MIN;
+//             if (td->td_sched->ts_ticks)
+//                     pri += min(SCHED_PRI_TICKS(td->td_sched),
+//                         SCHED_PRI_RANGE);
+//             pri += SCHED_PRI_NICE(td->td_proc->p_nice);
+//             KASSERT(pri >= PRI_MIN_BATCH && pri <= PRI_MAX_BATCH,
+//                 ("sched_priority: invalid priority %d: nice %d, "
+//                 "ticks %d ftick %d ltick %d tick pri %d",
+//                 pri, td->td_proc->p_nice, td->td_sched->ts_ticks,
+//                 td->td_sched->ts_ftick, td->td_sched->ts_ltick,
+//                 SCHED_PRI_TICKS(td->td_sched)));
+//     }
+//     sched_user_prio(td, pri);
 //
-///*
-// * Release a bound thread.
-// */
-//void
-//sched_unbind(struct thread *td)
+//     return;
+//}
+
+/*
+ * This routine enforces a maximum limit on the amount of scheduling history
+ * kept.  It is called after either the slptime or runtime is adjusted.  This
+ * function is ugly due to integer math.
+ */
+//static void
+//sched_interact_update(struct thread *td)
 //{
 //     struct td_sched *ts;
+//     u_int sum;
 //
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-//     KASSERT(td == curthread, ("sched_unbind: can only bind curthread"));
 //     ts = td->td_sched;
-//     if ((ts->ts_flags & TSF_BOUND) == 0)
+//     sum = ts->ts_runtime + ts->ts_slptime;
+//     if (sum < SCHED_SLP_RUN_MAX)
 //             return;
-//     ts->ts_flags &= ~TSF_BOUND;
-//     sched_unpin();
-//}
-//
-//int
-//sched_is_bound(struct thread *td)
-//{
-//     THREAD_LOCK_ASSERT(td, MA_OWNED);
-//     return (td->td_sched->ts_flags & TSF_BOUND);
-//}
-//
-///*
-// * Basic yield call.
-// */
-//void
-//sched_relinquish(struct thread *td)
-//{
-//     thread_lock(td);
-//     mi_switch(SW_VOL | SWT_RELINQUISH, NULL);
-//     thread_unlock(td);
-//}
-//
-///*
-// * Return the total system load.
-// */
-//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
-//}
-//
-//int
-//sched_sizeof_proc(void)
-//{
-//     return (sizeof(struct proc));
-//}
-//
-//int
-//sched_sizeof_thread(void)
-//{
-//     return (sizeof(struct thread) + sizeof(struct td_sched));
-//}
-//
-//#ifdef SMP
-//#define      TDQ_IDLESPIN(tdq)                                               \
-//    ((tdq)->tdq_cg != NULL && ((tdq)->tdq_cg->cg_flags & CG_FLAG_THREAD) == 0)
-//#else
-//#define      TDQ_IDLESPIN(tdq)       1
-//#endif
-//
-///*
-// * The actual idle process.
-// */
-//void
-//sched_idletd(void *dummy)
-//{
-//     struct thread *td;
-//     struct tdq *tdq;
-//     int switchcnt;
-//     int i;
-//
-//     mtx_assert(&Giant, MA_NOTOWNED);
-//     td = curthread;
-//     tdq = TDQ_SELF();
-//     for (;;) {
-//#ifdef SMP
-//             if (tdq_idled(tdq) == 0) {
-//                     continue;
-//             }
-//#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
-//              * may require an IPI.  However, don't do any busy
-//              * loops while on SMT machines as this simply steals
-//              * cycles from cores doing useful work.
-//              */
-//             if (TDQ_IDLESPIN(tdq) && switchcnt > sched_idlespinthresh) {
-//                     for (i = 0; i < sched_idlespins; i++) {
-//                             if (tdq->tdq_load)
-//                                     break;
-//                             cpu_spinwait();
-//                     }
-//             }
-//             switchcnt = tdq->tdq_switchcnt + tdq->tdq_oldswitchcnt;
-//             if (tdq->tdq_load == 0) {
-//                     tdq->tdq_cpu_idle = 1;
-//                     if (tdq->tdq_load == 0) {
-//                             cpu_idle(switchcnt > sched_idlespinthresh * 4);
-//                             tdq->tdq_switchcnt++;
-//                     }
-//                     tdq->tdq_cpu_idle = 0;
-//             }
-//             if (tdq->tdq_load) {
-//                     thread_lock(td);
-//                     mi_switch(SW_VOL | SWT_IDLE, NULL);
-//                     thread_unlock(td);
+//     /*
+//      * This only happens from two places:
+//      * 1) We have added an unusual amount of run time from fork_exit.
+//      * 2) We have added an unusual amount of sleep time from sched_sleep().
+//      */
+//     if (sum > SCHED_SLP_RUN_MAX * 2) {
+//             if (ts->ts_runtime > ts->ts_slptime) {
+//                     ts->ts_runtime = SCHED_SLP_RUN_MAX;
+//                     ts->ts_slptime = 1;
+//             } else {
+//                     ts->ts_slptime = SCHED_SLP_RUN_MAX;
+//                     ts->ts_runtime = 1;
 //             }
+//             return;
 //     }
-//}
-//
-///*
-// * A CPU is entering for the first time or a thread is exiting.
-// */
-//void
-//sched_throw(struct thread *td)
+//     /*
+//      * If we have exceeded by more than 1/5th then the algorithm below
+//      * will not bring us back into range.  Dividing by two here forces
+//      * us into the range of [4/5 * SCHED_INTERACT_MAX, SCHED_INTERACT_MAX]
+//      */
+//     if (sum > (SCHED_SLP_RUN_MAX / 5) * 6) {
+//             ts->ts_runtime /= 2;
+//             ts->ts_slptime /= 2;
+//             return;
+//     }
+//     ts->ts_runtime = (ts->ts_runtime / 5) * 4;
+//     ts->ts_slptime = (ts->ts_slptime / 5) * 4;
+//}
+
+/*
+ * Scale back the interactivity history when a child thread is created.  The
+ * history is inherited from the parent but the thread may behave totally
+ * differently.  For example, a shell spawning a compiler process.  We want
+ * to learn that the compiler is behaving badly very quickly.
+ */
+//static void
+//sched_interact_fork(struct thread *td)
 //{
-//     struct thread *newtd;
-//     struct tdq *tdq;
+//     int ratio;
+//     int sum;
 //
-//     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_load_rem(tdq, td);
-//             lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
+//     sum = td->td_sched->ts_runtime + td->td_sched->ts_slptime;
+//     if (sum > SCHED_SLP_RUN_FORK) {
+//             ratio = sum / SCHED_SLP_RUN_FORK;
+//             td->td_sched->ts_runtime /= ratio;
+//             td->td_sched->ts_slptime /= ratio;
 //     }
-//     KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
-//     newtd = choosethread();
-//     TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
-//     cpu_throw(td, newtd);           /* doesn't return */
 //}
+
+/*
+ * Called from proc0_init() to setup the scheduler fields.
+ */
+void
+schedinit(void)
+{
+
+       /*
+        * Set up the scheduler specific parts of proc0.
+        */
+       proc0.p_sched = NULL; /* XXX */
+       thread0.td_sched = &td_sched0;
+       td_sched0.ts_ltick = ticks;
+       td_sched0.ts_ftick = ticks;
+       td_sched0.ts_slice = sched_slice;
+}
+
+/*
+ * This is only somewhat accurate since given many processes of the same
+ * priority they will switch when their slices run out, which will be
+ * at most sched_slice stathz ticks.
+ */
+int
+sched_rr_interval(void)
+{
+
+       /* Convert sched_slice to hz */
+       return (hz/(realstathz/sched_slice));
+}
+
+/*
+ * Update the percent cpu tracking information when it is requested or
+ * the total history exceeds the maximum.  We keep a sliding history of
+ * tick counts that slowly decays.  This is less precise than the 4BSD
+ * mechanism since it happens with less regular and frequent events.
+ */
+//static void
+//sched_pctcpu_update(struct td_sched *ts, int run)
+//{
+//     int t = ticks;
 //
-///*
-// * 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)
+//     if (t - ts->ts_ltick >= SCHED_TICK_TARG) {
+//             ts->ts_ticks = 0;
+//             ts->ts_ftick = t - SCHED_TICK_TARG;
+//     } else if (t - ts->ts_ftick >= SCHED_TICK_MAX) {
+//             ts->ts_ticks = (ts->ts_ticks / (ts->ts_ltick - ts->ts_ftick)) *
+//                 (ts->ts_ltick - (t - SCHED_TICK_TARG));
+//             ts->ts_ftick = t - SCHED_TICK_TARG;
+//     }
+//     if (run)
+//             ts->ts_ticks += (t - ts->ts_ltick) << SCHED_TICK_SHIFT;
+//     ts->ts_ltick = t;
+//}
+
+/*
+ * Adjust the priority of a thread.  Move it to the appropriate run-queue
+ * if necessary.  This is the back-end for several priority related
+ * functions.
+ */
+//static void
+//sched_thread_priority(struct thread *td, u_char prio)
 //{
 //     struct td_sched *ts;
 //     struct tdq *tdq;
-//     int cpuid;
-//
+//     int oldpri;
+//
+//     KTR_POINT3(KTR_SCHED, "thread", sched_tdname(td), "prio",
+//         "prio:%d", td->td_priority, "new prio:%d", prio,
+//         KTR_ATTR_LINKED, sched_tdname(curthread));
+//     SDT_PROBE3(sched, , , change_pri, td, td->td_proc, prio);
+//     if (td != curthread && prio > td->td_priority) {
+//             KTR_POINT3(KTR_SCHED, "thread", sched_tdname(curthread),
+//                 "lend prio", "prio:%d", td->td_priority, "new prio:%d",
+//                 prio, KTR_ATTR_LINKED, sched_tdname(td));
+//             SDT_PROBE4(sched, , , lend_pri, td, td->td_proc, prio,
+//                 curthread);
+//     }
+//     ts = td->td_sched;
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     if (td->td_priority == prio)
+//             return;
 //     /*
-//      * Finish setting up thread glue so that it begins execution in a
-//      * non-nested critical section with the scheduler lock held.
+//      * If the priority has been elevated due to priority
+//      * propagation, we may have to move ourselves to a new
+//      * queue.  This could be optimized to not re-add in some
+//      * cases.
 //      */
-//     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__);
-//}
-//
-///*
-// * Create on first use to catch odd startup conditons.
-// */
-//char *
-//sched_tdname(struct thread *td)
-//{
-//#ifdef KTR
-//     struct td_sched *ts;
-//
-//     ts = td->td_sched;
-//     if (ts->ts_name[0] == '\0')
-//             snprintf(ts->ts_name, sizeof(ts->ts_name),
-//                 "%s tid %d", td->td_name, td->td_tid);
-//     return (ts->ts_name);
-//#else
-//     return (td->td_name);
-//#endif
-//}
+//     if (TD_ON_RUNQ(td) && prio < td->td_priority) {
+//             sched_rem(td);
+//             td->td_priority = prio;
+//             sched_add(td, SRQ_BORROWING);
+//             return;
+//     }
+//     /*
+//      * If the thread is currently running we may have to adjust the lowpri
+//      * information so other cpus are aware of our current priority.
+//      */
+//     if (TD_IS_RUNNING(td)) {
+//             tdq = TDQ_CPU(ts->ts_cpu);
+//             oldpri = td->td_priority;
+//             td->td_priority = prio;
+//             if (prio < tdq->tdq_lowpri)
+//                     tdq->tdq_lowpri = prio;
+//             else if (tdq->tdq_lowpri == oldpri)
+//                     tdq_setlowpri(tdq, td);
+//             return;
+//     }
+//     td->td_priority = prio;
+//}
+
+/*
+ * Update a thread's priority when it is lent another thread's
+ * priority.
+ */
+void
+sched_lend_prio(struct thread *td, u_char prio)
+{
+//
+//     td->td_flags |= TDF_BORROWING;
+//     sched_thread_priority(td, prio);
+}
+
+/*
+ * Restore a thread's priority when priority propagation is
+ * over.  The prio argument is the minimum priority the thread
+ * needs to have to satisfy other possible priority lending
+ * requests.  If the thread's regular priority is less
+ * important than prio, the thread will keep a priority boost
+ * of prio.
+ */
+void
+sched_unlend_prio(struct thread *td, u_char prio)
+{
+//     u_char base_pri;
+//
+//     if (td->td_base_pri >= PRI_MIN_TIMESHARE &&
+//         td->td_base_pri <= PRI_MAX_TIMESHARE)
+//             base_pri = td->td_user_pri;
+//     else
+//             base_pri = td->td_base_pri;
+//     if (prio >= base_pri) {
+//             td->td_flags &= ~TDF_BORROWING;
+//             sched_thread_priority(td, base_pri);
+//     } else
+//             sched_lend_prio(td, prio);
+}
+
+/*
+ * Standard entry for setting the priority to an absolute value.
+ */
+void
+sched_prio(struct thread *td, u_char prio)
+{
+       u_char oldprio;
+//
+//     /* First, update the base priority. */
+//     td->td_base_pri = prio;
+
+       oldprio = PVM;
+
+       if (TD_IS_IDLETHREAD(td)) {
+               oldprio = PRI_MAX_IDLE;
+       }
+
+       td->td_base_pri = oldprio;
+       td->td_priority = oldprio;
 //
-//#ifdef KTR
-//void
-//sched_clear_tdname(struct thread *td)
-//{
-//     struct td_sched *ts;
+//     /*
+//      * If the thread is borrowing another thread's priority, don't
+//      * ever lower the priority.
+//      */
+//     if (td->td_flags & TDF_BORROWING && td->td_priority < prio)
+//             return;
 //
-//     ts = td->td_sched;
-//     ts->ts_name[0] = '\0';
-//}
-//#endif
+//     /* Change the real priority. */
+//     oldprio = td->td_priority;
+////   sched_thread_priority(td, prio);
 //
-//#ifdef SMP
+//     /*
+//      * If the thread is on a turnstile, then let the turnstile update
+//      * its state.
+//      */
+//     if (TD_ON_LOCK(td) && oldprio != prio)
+//             turnstile_adjust(td, oldprio);
+}
+
+/*
+ * Set the base user priority, does not effect current running priority.
+ */
+void
+sched_user_prio(struct thread *td, u_char prio)
+{
+
+//     td->td_base_user_pri = prio;
+//     if (td->td_lend_user_pri <= prio)
+//             return;
+//     td->td_user_pri = prio;
+       td->td_base_user_pri = PVM;
+       td->td_user_pri = PVM;
+}
+
+void
+sched_lend_user_prio(struct thread *td, u_char prio)
+{
+
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     td->td_lend_user_pri = prio;
+//     td->td_user_pri = min(prio, td->td_base_user_pri);
+//     if (td->td_priority > td->td_user_pri)
+//             sched_prio(td, td->td_user_pri);
+//     else if (td->td_priority != td->td_user_pri)
+//             td->td_flags |= TDF_NEEDRESCHED;
+}
+
+/*
+ * 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));
+}
+
+/*
+ * Variadic version of thread_lock_unblock() that does not assume td_lock
+ * is blocked.
+ */
+static inline void
+thread_unblock_switch(struct thread *td, struct mtx *mtx)
+{
+       atomic_store_rel_ptr((volatile uintptr_t *)&td->td_lock,
+           (uintptr_t)mtx);
+}
+
+/*
+ * Switch threads.  This function has to handle threads coming in while
+ * blocked for some reason, running, or idle.  It also must deal with
+ * migrating a thread from one queue to another as running threads may
+ * be assigned elsewhere via binding.
+ */
+void
+sched_switch(struct thread *td, struct thread *newtd, int flags)
+{
+       struct tdq *tdq;
+       struct td_sched *ts;
+       struct mtx *mtx;
+       int srqflag;
+       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 {
+               /* This thread must be going to sleep. */
+               TDQ_LOCK(tdq);
+               mtx = thread_lock_block(td);
+               tdq_load_rem(tdq, td);
+       }
+       /*
+        * 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;
+}
+
+/*
+ * Adjust thread priorities as a result of a nice request.
+ */
+void
+sched_nice(struct proc *p, int nice)
+{
+//     struct thread *td;
 //
-///*
-// * Build the CPU topology dump string. Is recursively called to collect
-// * the topology tree.
-// */
-//static int
-//sysctl_kern_sched_topology_spec_internal(struct sbuf *sb, struct cpu_group *cg,
-//    int indent)
-//{
-//     char cpusetbuf[CPUSETBUFSIZ];
-//     int i, first;
+//     PROC_LOCK_ASSERT(p, MA_OWNED);
 //
-//     sbuf_printf(sb, "%*s<group level=\"%d\" cache-level=\"%d\">\n", indent,
-//         "", 1 + indent / 2, cg->cg_level);
-//     sbuf_printf(sb, "%*s <cpu count=\"%d\" mask=\"%s\">", indent, "",
-//         cg->cg_count, cpusetobj_strprint(cpusetbuf, &cg->cg_mask));
-//     first = TRUE;
-//     for (i = 0; i < MAXCPU; i++) {
-//             if (CPU_ISSET(i, &cg->cg_mask)) {
-//                     if (!first)
-//                             sbuf_printf(sb, ", ");
-//                     else
-//                             first = FALSE;
-//                     sbuf_printf(sb, "%d", i);
-//             }
+//     p->p_nice = nice;
+//     FOREACH_THREAD_IN_PROC(p, td) {
+//             thread_lock(td);
+//             sched_priority(td);
+//             sched_prio(td, td->td_base_user_pri);
+//             thread_unlock(td);
 //     }
-//     sbuf_printf(sb, "</cpu>\n");
+}
+
+/*
+ * Record the sleep time for the interactivity scorer.
+ */
+void
+sched_sleep(struct thread *td, int prio)
+{
+
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
 //
-//     if (cg->cg_flags != 0) {
-//             sbuf_printf(sb, "%*s <flags>", indent, "");
-//             if ((cg->cg_flags & CG_FLAG_HTT) != 0)
-//                     sbuf_printf(sb, "<flag name=\"HTT\">HTT group</flag>");
-//             if ((cg->cg_flags & CG_FLAG_THREAD) != 0)
-//                     sbuf_printf(sb, "<flag name=\"THREAD\">THREAD group</flag>");
-//             if ((cg->cg_flags & CG_FLAG_SMT) != 0)
-//                     sbuf_printf(sb, "<flag name=\"SMT\">SMT group</flag>");
-//             sbuf_printf(sb, "</flags>\n");
+//     td->td_slptick = ticks;
+//     if (TD_IS_SUSPENDED(td) || prio >= PSOCK)
+//             td->td_flags |= TDF_CANSWAP;
+//     if (PRI_BASE(td->td_pri_class) != PRI_TIMESHARE)
+//             return;
+//     if (static_boost == 1 && prio)
+//             sched_prio(td, prio);
+//     else if (static_boost && td->td_priority > static_boost)
+//             sched_prio(td, static_boost);
+}
+
+/*
+ * 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)
+{
+       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);
+}
+
+/*
+ * Penalize the parent for creating a new child and initialize the child's
+ * priority.
+ */
+void
+sched_fork(struct thread *td, struct thread *child)
+{
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     sched_pctcpu_update(td->td_sched, 1);
+       sched_fork_thread(td, child);
+       /*
+        * Penalize the parent and child for forking.
+        */
+//     sched_interact_fork(child);
+//     sched_priority(child);
+       td->td_sched->ts_runtime += tickincr;
+//     sched_interact_update(td);
+//     sched_priority(td);
+}
+
+/*
+ * Fork a new thread, may be within the same process.
+ */
+void
+sched_fork_thread(struct thread *td, struct thread *child)
+{
+       struct td_sched *ts;
+       struct td_sched *ts2;
+
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+       /*
+        * Initialize child.
+        */
+       ts = td->td_sched;
+       ts2 = child->td_sched;
+       child->td_lock = TDQ_LOCKPTR(TDQ_SELF());
+       child->td_cpuset = cpuset_ref(td->td_cpuset);
+       ts2->ts_cpu = ts->ts_cpu;
+       ts2->ts_flags = 0;
+       /*
+        * Grab our parents cpu estimation information.
+        */
+       ts2->ts_ticks = ts->ts_ticks;
+       ts2->ts_ltick = ts->ts_ltick;
+       ts2->ts_ftick = ts->ts_ftick;
+       /*
+        * Do not inherit any borrowed priority from the parent.
+        */
+       child->td_priority = child->td_base_pri;
+       /*
+        * And update interactivity score.
+        */
+       ts2->ts_slptime = ts->ts_slptime;
+       ts2->ts_runtime = ts->ts_runtime;
+       ts2->ts_slice = 1;      /* Attempt to quickly learn interactivity. */
+#ifdef KTR
+       bzero(ts2->ts_name, sizeof(ts2->ts_name));
+#endif
+}
+
+/*
+ * Adjust the priority class of a thread.
+ */
+void
+sched_class(struct thread *td, int class)
+{
+
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+       if (td->td_pri_class == class)
+               return;
+       td->td_pri_class = class;
+}
+
+/*
+ * Return some of the child's priority and interactivity to the parent.
+ */
+void
+sched_exit(struct proc *p, struct thread *child)
+{
+//     struct thread *td;
 //
-//     if (cg->cg_children > 0) {
-//             sbuf_printf(sb, "%*s <children>\n", indent, "");
-//             for (i = 0; i < cg->cg_children; i++)
-//                     sysctl_kern_sched_topology_spec_internal(sb,
-//                         &cg->cg_child[i], indent+2);
-//             sbuf_printf(sb, "%*s </children>\n", indent, "");
+//     KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "proc exit",
+//         "prio:%d", child->td_priority);
+//     PROC_LOCK_ASSERT(p, MA_OWNED);
+//     td = FIRST_THREAD_IN_PROC(p);
+//     sched_exit_thread(td, child);
+}
+
+/*
+ * Penalize another thread for the time spent on this one.  This helps to
+ * worsen the priority and interactivity of processes which schedule batch
+ * jobs such as make.  This has little effect on the make process itself but
+ * causes new processes spawned by it to receive worse scores immediately.
+ */
+void
+sched_exit_thread(struct thread *td, struct thread *child)
+{
+
+//     KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "thread exit",
+//         "prio:%d", child->td_priority);
+//     /*
+//      * Give the child's runtime to the parent without returning the
+//      * sleep time as a penalty to the parent.  This causes shells that
+//      * launch expensive things to mark their children as expensive.
+//      */
+//     thread_lock(td);
+//     td->td_sched->ts_runtime += child->td_sched->ts_runtime;
+//     sched_interact_update(td);
+//     sched_priority(td);
+//     thread_unlock(td);
+}
+
+/*
+ * Used by void ipi_bitmap_handler(struct trapframe frame);
+ * sys/amd64/amd64/mp_machdep.c:1267
+ */
+void
+sched_preempt(struct thread *td)
+{
+       struct tdq *tdq;
+
+       SDT_PROBE2(sched, , , surrender, td, td->td_proc);
+
+       thread_lock(td);
+       tdq = TDQ_SELF();
+       TDQ_LOCK_ASSERT(tdq, MA_OWNED);
+       tdq->tdq_ipipending = 0;
+//     if (td->td_priority > tdq->tdq_lowpri) {
+               int flags;
+
+               flags = SW_INVOL | SW_PREEMPT;
+               if (td->td_critnest > 1)
+                       td->td_owepreempt = 1;
+               else if (TD_IS_IDLETHREAD(td))
+                       mi_switch(flags | SWT_REMOTEWAKEIDLE, NULL);
+               else
+                       mi_switch(flags | SWT_REMOTEPREEMPT, NULL);
 //     }
-//     sbuf_printf(sb, "%*s</group>\n", indent, "");
-//     return (0);
-//}
-//
-///*
-// * Sysctl handler for retrieving topology dump. It's a wrapper for
-// * the recursive sysctl_kern_smp_topology_spec_internal().
-// */
-//static int
-//sysctl_kern_sched_topology_spec(SYSCTL_HANDLER_ARGS)
-//{
-//     struct sbuf *topo;
-//     int err;
-//
-//     KASSERT(cpu_top != NULL, ("cpu_top isn't initialized"));
-//
-//     topo = sbuf_new(NULL, NULL, 500, SBUF_AUTOEXTEND);
-//     if (topo == NULL)
-//             return (ENOMEM);
-//
-//     sbuf_printf(topo, "<groups>\n");
-//     err = sysctl_kern_sched_topology_spec_internal(topo, cpu_top, 1);
-//     sbuf_printf(topo, "</groups>\n");
-//
-//     if (err == 0) {
-//             sbuf_finish(topo);
-//             err = SYSCTL_OUT(req, sbuf_data(topo), sbuf_len(topo));
+       thread_unlock(td);
+}
+
+/*
+ * Fix priorities on return to user-space.  Priorities may be elevated due
+ * to static priorities in msleep() or similar.
+ */
+void
+sched_userret(struct thread *td)
+{
+//     /*
+//      * XXX we cheat slightly on the locking here to avoid locking in
+//      * the usual case.  Setting td_priority here is essentially an
+//      * incomplete workaround for not setting it properly elsewhere.
+//      * Now that some interrupt handlers are threads, not setting it
+//      * properly elsewhere can clobber it in the window between setting
+//      * it here and returning to user mode, so don't waste time setting
+//      * it perfectly here.
+//      */
+//     KASSERT((td->td_flags & TDF_BORROWING) == 0,
+//         ("thread with borrowed priority returning to userland"));
+//     if (td->td_priority != td->td_user_pri) {
+//             thread_lock(td);
+//             td->td_priority = td->td_user_pri;
+//             td->td_base_pri = td->td_user_pri;
+//             tdq_setlowpri(TDQ_SELF(), td);
+//             thread_unlock(td);
+//    }
+}
+
+/*
+ * Handle a stathz tick.  This is really only relevant for timeshare
+ * threads.
+ */
+void
+sched_clock(struct thread *td)
+{
+       struct tdq *tdq;
+       struct td_sched *ts;
+
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+       tdq = TDQ_SELF();
+#ifdef SMP
+       /*
+        * We run the long term load balancer infrequently on the first cpu.
+        */
+//     if (balance_tdq == tdq) {
+//             if (balance_ticks && --balance_ticks == 0)
+//                     sched_balance();
 //     }
-//     sbuf_delete(topo);
-//     return (err);
-//}
-//
-//#endif
-//
-//SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler");
-//SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "ULE", 0,
-//    "Scheduler name");
-//SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
-//    "Slice size for timeshare threads");
-//SYSCTL_INT(_kern_sched, OID_AUTO, interact, CTLFLAG_RW, &sched_interact, 0,
-//     "Interactivity score threshold");
-//SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW, &preempt_thresh,
-//     0,"Min priority for preemption, lower priorities have greater precedence");
-//SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost,
-//     0,"Controls whether static kernel priorities are assigned to sleeping threads.");
-//SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins,
-//     0,"Number of times idle will spin waiting for new work.");
-//SYSCTL_INT(_kern_sched, OID_AUTO, idlespinthresh, CTLFLAG_RW, &sched_idlespinthresh,
-//     0,"Threshold before we will permit idle spinning.");
+#endif
+       /*
+        * Save the old switch count so we have a record of the last ticks
+        * activity.   Initialize the new switch count based on our load.
+        * If there is some activity seed it to reflect that.
+        */
+       tdq->tdq_oldswitchcnt = tdq->tdq_switchcnt;
+       tdq->tdq_switchcnt = tdq->tdq_load;
+       /*
+        * Advance the insert index once for each tick to ensure that all
+        * threads get a chance to run.
+        */
+       if (tdq->tdq_idx == tdq->tdq_ridx) {
+               tdq->tdq_idx = (tdq->tdq_idx + 1) % RQ_NQS;
+               if (TAILQ_EMPTY(&tdq->tdq_timeshare.rq_queues[tdq->tdq_ridx]))
+                       tdq->tdq_ridx = tdq->tdq_idx;
+       }
+       ts = td->td_sched;
+//     sched_pctcpu_update(ts, 1);
+       if (td->td_pri_class & PRI_FIFO_BIT)
+               return;
+       if (PRI_BASE(td->td_pri_class) == PRI_TIMESHARE) {
+               /*
+                * We used a tick; charge it to the thread so
+                * that we can compute our interactivity.
+                */
+               td->td_sched->ts_runtime += tickincr;
+//             sched_interact_update(td);
+//             sched_priority(td);
+       }
+       /*
+        * We used up one time slice.
+        */
+       if (--ts->ts_slice > 0)
+               return;
+       /*
+        * We're out of time, force a requeue at userret().
+        */
+       ts->ts_slice = sched_slice;
+       td->td_flags |= TDF_NEEDRESCHED;
+}
+
+/*
+ * Called once per hz tick.
+ */
+void
+sched_tick(int cnt)
+{
+
+}
+
+/*
+ * Return whether the current CPU has runnable tasks.  Used for in-kernel
+ * cooperative idle threads.
+ */
+int
+sched_runnable(void)
+{
+       struct tdq *tdq;
+       int load;
+
+       load = 1;
+
+       tdq = TDQ_SELF();
+       if ((curthread->td_flags & TDF_IDLETD) != 0) {
+               if (tdq->tdq_load > 0)
+                       goto out;
+       } else
+               if (tdq->tdq_load - 1 > 0)
+                       goto out;
+       load = 0;
+out:
+       return (load);
+}
+
+/*
+ * Choose the highest priority thread to run.  The thread is removed from
+ * the run-queue while running however the load remains.  For SMP we set
+ * the tdq in the global idle bitmask if it idles here.
+ */
+struct thread *
+sched_choose(void)
+{
+       struct thread *td;
+       struct tdq *tdq;
+
+       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
+sched_setpreempt(struct thread *td)
+{
+       struct thread *ctd;
+       int cpri;
+       int pri;
+
+       THREAD_LOCK_ASSERT(curthread, MA_OWNED);
+
+       ctd = curthread;
+       pri = td->td_priority;
+       cpri = ctd->td_priority;
+       if (pri < cpri)
+               ctd->td_flags |= TDF_NEEDRESCHED;
+       if (panicstr != NULL || pri >= cpri || cold || TD_IS_INHIBITED(ctd))
+               return;
+       if (!sched_shouldpreempt(pri, cpri, 0))
+               return;
+       ctd->td_owepreempt = 1;
+}
+
+/*
+ * Add a thread to a thread queue.  Select the appropriate runq and add the
+ * thread to it.  This is the internal function called when the tdq is
+ * predetermined.
+ */
+void
+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);
+       tdq_load_add(tdq, td);
+}
+
+/*
+ * Select the target thread queue and add a thread to it.  Request
+ * preemption or IPI a remote processor if required.
+ */
+void
+sched_add(struct thread *td, int flags)
+{
+       struct tdq *tdq;
+#ifdef SMP
+       int cpu;
+#endif
+
+//     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));
+       tdq_add(tdq, td, flags);
+#endif
+       if (!(flags & SRQ_YIELDING))
+               sched_setpreempt(td);
+}
+
+/*
+ * Remove a thread from a run-queue without running it.  This is used
+ * when we're stealing a thread from a remote queue.  Otherwise all threads
+ * exit by calling sched_exit_thread() and sched_throw() themselves.
+ */
+void
+sched_rem(struct thread *td)
+{
+       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_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);
+}
+
+/*
+ * Fetch cpu utilization information.  Updates on demand.
+ */
+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);
+//     sched_pctcpu_update(ts, TD_IS_RUNNING(td));
+//     if (ts->ts_ticks) {
+//             int rtick;
+//
+//             /* How many rtick per second ? */
+//             rtick = min(SCHED_TICK_HZ(ts) / SCHED_TICK_SECS, hz);
+//             pctcpu = (FSCALE * ((FSCALE * rtick)/hz)) >> FSHIFT;
+//     }
+
+       return (pctcpu);
+}
+
+/*
+ * Enforce affinity settings for a thread.  Called after adjustments to
+ * cpumask.
+ */
+void
+sched_affinity(struct thread *td)
+{
 //#ifdef SMP
-//SYSCTL_INT(_kern_sched, OID_AUTO, affinity, CTLFLAG_RW, &affinity, 0,
-//    "Number of hz ticks to keep thread affinity for");
-//SYSCTL_INT(_kern_sched, OID_AUTO, balance, CTLFLAG_RW, &rebalance, 0,
-//    "Enables the long-term load balancer");
-//SYSCTL_INT(_kern_sched, OID_AUTO, balance_interval, CTLFLAG_RW,
-//    &balance_interval, 0,
-//    "Average frequency in stathz ticks to run the long-term balancer");
-//SYSCTL_INT(_kern_sched, OID_AUTO, steal_idle, CTLFLAG_RW, &steal_idle, 0,
-//    "Attempts to steal work from other cores before idling");
-//SYSCTL_INT(_kern_sched, OID_AUTO, steal_thresh, CTLFLAG_RW, &steal_thresh, 0,
-//    "Minimum load on remote cpu before we'll steal");
-//
-///* Retrieve SMP topology */
-//SYSCTL_PROC(_kern_sched, OID_AUTO, topology_spec, CTLTYPE_STRING |
-//    CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A",
-//    "XML dump of detected CPU topology");
+//     struct td_sched *ts;
 //
+//     THREAD_LOCK_ASSERT(td, MA_OWNED);
+//     ts = td->td_sched;
+//     if (THREAD_CAN_SCHED(td, ts->ts_cpu))
+//             return;
+//     if (TD_ON_RUNQ(td)) {
+//             sched_rem(td);
+//             sched_add(td, SRQ_BORING);
+//             return;
+//     }
+//     if (!TD_IS_RUNNING(td))
+//             return;
+//     /*
+//      * Force a switch before returning to userspace.  If the
+//      * target thread is not running locally send an ipi to force
+//      * the issue.
+//      */
+//     td->td_flags |= TDF_NEEDRESCHED;
+//     if (td != curthread) {
+////           printf("Sending IPI_PREEMPT2 from %d to %d\n", curcpu, ts->ts_cpu);
+//             ipi_cpu(ts->ts_cpu, IPI_PREEMPT);
+//     }
 //#endif
-//
-///* ps compat.  All cpu percentages from ULE are weighted. */
-//static int ccpu = 0;
-//SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, "");
+}
+
+/*
+ * Bind a thread to a target cpu.
+ */
+void
+sched_bind(struct thread *td, int cpu)
+{
+       struct td_sched *ts;
+
+       THREAD_LOCK_ASSERT(td, MA_OWNED|MA_NOTRECURSED);
+       KASSERT(td == curthread, ("sched_bind: can only bind curthread"));
+       ts = td->td_sched;
+       if (ts->ts_flags & TSF_BOUND)
+               sched_unbind(td);
+       KASSERT(THREAD_CAN_MIGRATE(td), ("%p must be migratable", td));
+       ts->ts_flags |= TSF_BOUND;
+       sched_pin();
+       if (PCPU_GET(cpuid) == cpu)
+               return;
+       ts->ts_cpu = cpu;
+       /* When we return from mi_switch we'll be on the correct cpu. */
+       mi_switch(SW_VOL, NULL);
+}
+
+/*
+ * Release a bound thread.
+ */
+void
+sched_unbind(struct thread *td)
+{
+       struct td_sched *ts;
+
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+       KASSERT(td == curthread, ("sched_unbind: can only bind curthread"));
+       ts = td->td_sched;
+       if ((ts->ts_flags & TSF_BOUND) == 0)
+               return;
+       ts->ts_flags &= ~TSF_BOUND;
+       sched_unpin();
+}
+
+int
+sched_is_bound(struct thread *td)
+{
+       THREAD_LOCK_ASSERT(td, MA_OWNED);
+       return (td->td_sched->ts_flags & TSF_BOUND);
+}
+
+/*
+ * Basic yield call.
+ */
+void
+sched_relinquish(struct thread *td)
+{
+       thread_lock(td);
+       mi_switch(SW_VOL | SWT_RELINQUISH, NULL);
+       thread_unlock(td);
+}
+
+/*
+ * Return the total system load.
+ */
+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
+}
+
+int
+sched_sizeof_proc(void)
+{
+       return (sizeof(struct proc));
+}
+
+int
+sched_sizeof_thread(void)
+{
+       return (sizeof(struct thread) + sizeof(struct td_sched));
+}
+
+#ifdef SMP
+#define        TDQ_IDLESPIN(tdq)                                               \
+    ((tdq)->tdq_cg != NULL && ((tdq)->tdq_cg->cg_flags & CG_FLAG_THREAD) == 0)
+#else
+#define        TDQ_IDLESPIN(tdq)       1
+#endif
+
+/*
+ * The actual idle process.
+ */
+void
+sched_idletd(void *dummy)
+{
+       struct thread *td;
+       struct tdq *tdq;
+       int switchcnt;
+       int i;
+
+       mtx_assert(&Giant, MA_NOTOWNED);
+       td = curthread;
+       tdq = TDQ_SELF();
+       for (;;) {
+#ifdef SMP
+               if (tdq_idled(tdq) == 0) {
+                       continue;
+               }
+#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
+                * may require an IPI.  However, don't do any busy
+                * loops while on SMT machines as this simply steals
+                * cycles from cores doing useful work.
+                */
+               if (TDQ_IDLESPIN(tdq) && switchcnt > sched_idlespinthresh) {
+                       for (i = 0; i < sched_idlespins; i++) {
+                               if (tdq->tdq_load)
+                                       break;
+                               cpu_spinwait();
+                       }
+               }
+               switchcnt = tdq->tdq_switchcnt + tdq->tdq_oldswitchcnt;
+               if (tdq->tdq_load == 0) {
+                       tdq->tdq_cpu_idle = 1;
+                       if (tdq->tdq_load == 0) {
+                               cpu_idle(switchcnt > sched_idlespinthresh * 4);
+                               tdq->tdq_switchcnt++;
+                       }
+                       tdq->tdq_cpu_idle = 0;
+               }
+               if (tdq->tdq_load) {
+                       thread_lock(td);
+                       mi_switch(SW_VOL | SWT_IDLE, NULL);
+                       thread_unlock(td);
+               }
+       }
+}
+
+/*
+ * A CPU is entering for the first time or a thread is exiting.
+ */
+void
+sched_throw(struct thread *td)
+{
+       struct thread *newtd;
+       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_load_rem(tdq, td);
+               lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
+       }
+       KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
+       newtd = choosethread();
+       TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
+       cpu_throw(td, newtd);           /* doesn't return */
+}
+
+/*
+ * 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__);
+}
+
+/*
+ * Create on first use to catch odd startup conditons.
+ */
+char *
+sched_tdname(struct thread *td)
+{
+#ifdef KTR
+       struct td_sched *ts;
+
+       ts = td->td_sched;
+       if (ts->ts_name[0] == '\0')
+               snprintf(ts->ts_name, sizeof(ts->ts_name),
+                   "%s tid %d", td->td_name, td->td_tid);
+       return (ts->ts_name);
+#else
+       return (td->td_name);
+#endif
+}
+
+#ifdef KTR
+void
+sched_clear_tdname(struct thread *td)
+{
+       struct td_sched *ts;
+
+       ts = td->td_sched;
+       ts->ts_name[0] = '\0';
+}
+#endif
+
+#ifdef SMP
+
+/*
+ * Build the CPU topology dump string. Is recursively called to collect
+ * the topology tree.
+ */
+static int
+sysctl_kern_sched_topology_spec_internal(struct sbuf *sb, struct cpu_group *cg,
+    int indent)
+{
+       char cpusetbuf[CPUSETBUFSIZ];
+       int i, first;
+
+       sbuf_printf(sb, "%*s<group level=\"%d\" cache-level=\"%d\">\n", indent,
+           "", 1 + indent / 2, cg->cg_level);
+       sbuf_printf(sb, "%*s <cpu count=\"%d\" mask=\"%s\">", indent, "",
+           cg->cg_count, cpusetobj_strprint(cpusetbuf, &cg->cg_mask));
+       first = TRUE;
+       for (i = 0; i < MAXCPU; i++) {
+               if (CPU_ISSET(i, &cg->cg_mask)) {
+                       if (!first)
+                               sbuf_printf(sb, ", ");
+                       else
+                               first = FALSE;
+                       sbuf_printf(sb, "%d", i);
+               }
+       }
+       sbuf_printf(sb, "</cpu>\n");
+
+       if (cg->cg_flags != 0) {
+               sbuf_printf(sb, "%*s <flags>", indent, "");
+               if ((cg->cg_flags & CG_FLAG_HTT) != 0)
+                       sbuf_printf(sb, "<flag name=\"HTT\">HTT group</flag>");
+               if ((cg->cg_flags & CG_FLAG_THREAD) != 0)
+                       sbuf_printf(sb, "<flag name=\"THREAD\">THREAD group</flag>");
+               if ((cg->cg_flags & CG_FLAG_SMT) != 0)
+                       sbuf_printf(sb, "<flag name=\"SMT\">SMT group</flag>");
+               sbuf_printf(sb, "</flags>\n");
+       }
+
+       if (cg->cg_children > 0) {
+               sbuf_printf(sb, "%*s <children>\n", indent, "");
+               for (i = 0; i < cg->cg_children; i++)
+                       sysctl_kern_sched_topology_spec_internal(sb,
+                           &cg->cg_child[i], indent+2);
+               sbuf_printf(sb, "%*s </children>\n", indent, "");
+       }
+       sbuf_printf(sb, "%*s</group>\n", indent, "");
+       return (0);
+}
+
+/*
+ * Sysctl handler for retrieving topology dump. It's a wrapper for
+ * the recursive sysctl_kern_smp_topology_spec_internal().
+ */
+static int
+sysctl_kern_sched_topology_spec(SYSCTL_HANDLER_ARGS)
+{
+       struct sbuf *topo;
+       int err;
+
+       KASSERT(cpu_top != NULL, ("cpu_top isn't initialized"));
+
+       topo = sbuf_new(NULL, NULL, 500, SBUF_AUTOEXTEND);
+       if (topo == NULL)
+               return (ENOMEM);
+
+       sbuf_printf(topo, "<groups>\n");
+       err = sysctl_kern_sched_topology_spec_internal(topo, cpu_top, 1);
+       sbuf_printf(topo, "</groups>\n");
+
+       if (err == 0) {
+               sbuf_finish(topo);
+               err = SYSCTL_OUT(req, sbuf_data(topo), sbuf_len(topo));
+       }
+       sbuf_delete(topo);
+       return (err);
+}
+
+#endif
+
+SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler");
+SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "ULE", 0,
+    "Scheduler name");
+SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
+    "Slice size for timeshare threads");
+SYSCTL_INT(_kern_sched, OID_AUTO, interact, CTLFLAG_RW, &sched_interact, 0,
+     "Interactivity score threshold");
+SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW, &preempt_thresh,
+     0,"Min priority for preemption, lower priorities have greater precedence");
+SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost,
+     0,"Controls whether static kernel priorities are assigned to sleeping threads.");
+SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins,
+     0,"Number of times idle will spin waiting for new work.");
+SYSCTL_INT(_kern_sched, OID_AUTO, idlespinthresh, CTLFLAG_RW, &sched_idlespinthresh,
+     0,"Threshold before we will permit idle spinning.");
+#ifdef SMP
+SYSCTL_INT(_kern_sched, OID_AUTO, affinity, CTLFLAG_RW, &affinity, 0,
+    "Number of hz ticks to keep thread affinity for");
+SYSCTL_INT(_kern_sched, OID_AUTO, balance, CTLFLAG_RW, &rebalance, 0,
+    "Enables the long-term load balancer");
+SYSCTL_INT(_kern_sched, OID_AUTO, balance_interval, CTLFLAG_RW,
+    &balance_interval, 0,
+    "Average frequency in stathz ticks to run the long-term balancer");
+SYSCTL_INT(_kern_sched, OID_AUTO, steal_idle, CTLFLAG_RW, &steal_idle, 0,
+    "Attempts to steal work from other cores before idling");
+SYSCTL_INT(_kern_sched, OID_AUTO, steal_thresh, CTLFLAG_RW, &steal_thresh, 0,
+    "Minimum load on remote cpu before we'll steal");
+
+/* Retrieve SMP topology */
+SYSCTL_PROC(_kern_sched, OID_AUTO, topology_spec, CTLTYPE_STRING |
+    CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A",
+    "XML dump of detected CPU topology");
+
+#endif
+
+/* ps compat.  All cpu percentages from ULE are weighted. */
+static int ccpu = 0;
+SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, "");