Attachment 'litmus-rt-2012.1.patch'

Download

   1  Makefile                                    |    4 +-
   2  arch/arm/Kconfig                            |    8 +
   3  arch/arm/include/asm/timex.h                |    2 +
   4  arch/arm/include/asm/unistd.h               |    3 +
   5  arch/arm/kernel/calls.S                     |   12 +
   6  arch/arm/kernel/smp.c                       |    4 +
   7  arch/arm/mach-realview/include/mach/timex.h |   27 +
   8  arch/x86/Kconfig                            |    8 +
   9  arch/x86/include/asm/entry_arch.h           |    1 +
  10  arch/x86/include/asm/feather_trace.h        |   17 +
  11  arch/x86/include/asm/feather_trace_32.h     |   79 ++
  12  arch/x86/include/asm/feather_trace_64.h     |   67 ++
  13  arch/x86/include/asm/hw_irq.h               |    3 +
  14  arch/x86/include/asm/irq_vectors.h          |    7 +
  15  arch/x86/include/asm/processor.h            |    4 +
  16  arch/x86/include/asm/unistd_32.h            |    6 +-
  17  arch/x86/include/asm/unistd_64.h            |    4 +
  18  arch/x86/kernel/Makefile                    |    2 +
  19  arch/x86/kernel/cpu/intel_cacheinfo.c       |   17 +
  20  arch/x86/kernel/entry_64.S                  |    2 +
  21  arch/x86/kernel/ft_event.c                  |  118 +++
  22  arch/x86/kernel/irqinit.c                   |    3 +
  23  arch/x86/kernel/smp.c                       |   31 +
  24  arch/x86/kernel/syscall_table_32.S          |   12 +
  25  fs/exec.c                                   |   13 +-
  26  fs/inode.c                                  |    2 +
  27  include/linux/completion.h                  |    1 +
  28  include/linux/fs.h                          |   21 +-
  29  include/linux/hardirq.h                     |    4 +
  30  include/linux/hrtimer.h                     |   32 +
  31  include/linux/sched.h                       |   19 +-
  32  include/linux/smp.h                         |    5 +
  33  include/linux/tick.h                        |    5 +
  34  include/litmus/affinity.h                   |   80 ++
  35  include/litmus/bheap.h                      |   77 ++
  36  include/litmus/budget.h                     |    8 +
  37  include/litmus/clustered.h                  |   44 ++
  38  include/litmus/debug_trace.h                |   37 +
  39  include/litmus/edf_common.h                 |   25 +
  40  include/litmus/fdso.h                       |   71 ++
  41  include/litmus/feather_buffer.h             |   94 +++
  42  include/litmus/feather_trace.h              |   65 ++
  43  include/litmus/ftdev.h                      |   55 ++
  44  include/litmus/jobs.h                       |    9 +
  45  include/litmus/litmus.h                     |  275 +++++++
  46  include/litmus/litmus_proc.h                |   25 +
  47  include/litmus/locking.h                    |   28 +
  48  include/litmus/preempt.h                    |  164 ++++
  49  include/litmus/rt_domain.h                  |  182 +++++
  50  include/litmus/rt_param.h                   |  209 ++++++
  51  include/litmus/sched_plugin.h               |  111 +++
  52  include/litmus/sched_trace.h                |  200 +++++
  53  include/litmus/srp.h                        |   28 +
  54  include/litmus/trace.h                      |  116 +++
  55  include/litmus/trace_irq.h                  |   21 +
  56  include/litmus/unistd_32.h                  |   21 +
  57  include/litmus/unistd_64.h                  |   33 +
  58  kernel/exit.c                               |    4 +
  59  kernel/fork.c                               |    7 +
  60  kernel/hrtimer.c                            |   95 +++
  61  kernel/printk.c                             |   14 +-
  62  kernel/sched.c                              |  137 ++++-
  63  kernel/sched_fair.c                         |    3 +
  64  kernel/sched_rt.c                           |    2 +-
  65  kernel/time/tick-sched.c                    |   47 ++
  66  litmus/Kconfig                              |  218 ++++++
  67  litmus/Makefile                             |   29 +
  68  litmus/affinity.c                           |   42 ++
  69  litmus/bheap.c                              |  314 ++++++++
  70  litmus/budget.c                             |  111 +++
  71  litmus/clustered.c                          |  111 +++
  72  litmus/ctrldev.c                            |  150 ++++
  73  litmus/edf_common.c                         |  118 +++
  74  litmus/fdso.c                               |  293 ++++++++
  75  litmus/ft_event.c                           |   43 ++
  76  litmus/ftdev.c                              |  439 +++++++++++
  77  litmus/jobs.c                               |   43 ++
  78  litmus/litmus.c                             |  564 ++++++++++++++
  79  litmus/litmus_proc.c                        |  347 +++++++++
  80  litmus/locking.c                            |  139 ++++
  81  litmus/preempt.c                            |  133 ++++
  82  litmus/rt_domain.c                          |  357 +++++++++
  83  litmus/sched_cedf.c                         |  863 ++++++++++++++++++++++
  84  litmus/sched_gsn_edf.c                      | 1030 ++++++++++++++++++++++++++
  85  litmus/sched_litmus.c                       |  325 ++++++++
  86  litmus/sched_pfair.c                        | 1067 +++++++++++++++++++++++++++
  87  litmus/sched_plugin.c                       |  227 ++++++
  88  litmus/sched_psn_edf.c                      |  645 ++++++++++++++++
  89  litmus/sched_task_trace.c                   |  241 ++++++
  90  litmus/sched_trace.c                        |  252 +++++++
  91  litmus/srp.c                                |  295 ++++++++
  92  litmus/sync.c                               |  104 +++
  93  litmus/trace.c                              |  225 ++++++
  94  93 files changed, 11521 insertions(+), 34 deletions(-)
  95 
  96 diff --git a/Makefile b/Makefile
  97 index 6a5bdad..a327725 100644
  98 --- a/Makefile
  99 +++ b/Makefile
 100 @@ -1,7 +1,7 @@
 101  VERSION = 3
 102  PATCHLEVEL = 0
 103  SUBLEVEL = 0
 104 -EXTRAVERSION =
 105 +EXTRAVERSION =-litmus
 106  NAME = Sneaky Weasel
 107  
 108  # *DOCUMENTATION*
 109 @@ -708,7 +708,7 @@ export mod_strip_cmd
 110  
 111  
 112  ifeq ($(KBUILD_EXTMOD),)
 113 -core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
 114 +core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/ litmus/
 115  
 116  vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
 117  		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
 118 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
 119 index 9adc278..fb228ea 100644
 120 --- a/arch/arm/Kconfig
 121 +++ b/arch/arm/Kconfig
 122 @@ -2040,3 +2040,11 @@ source "security/Kconfig"
 123  source "crypto/Kconfig"
 124  
 125  source "lib/Kconfig"
 126 +
 127 +config ARCH_HAS_SEND_PULL_TIMERS
 128 +	def_bool n
 129 +
 130 +config ARCH_HAS_FEATHER_TRACE
 131 +	def_bool n
 132 +
 133 +source "litmus/Kconfig"
 134 diff --git a/arch/arm/include/asm/timex.h b/arch/arm/include/asm/timex.h
 135 index 3be8de3..8a102a3 100644
 136 --- a/arch/arm/include/asm/timex.h
 137 +++ b/arch/arm/include/asm/timex.h
 138 @@ -16,9 +16,11 @@
 139  
 140  typedef unsigned long cycles_t;
 141  
 142 +#ifndef get_cycles
 143  static inline cycles_t get_cycles (void)
 144  {
 145  	return 0;
 146  }
 147 +#endif
 148  
 149  #endif
 150 diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
 151 index 2c04ed5..0196edf 100644
 152 --- a/arch/arm/include/asm/unistd.h
 153 +++ b/arch/arm/include/asm/unistd.h
 154 @@ -403,6 +403,9 @@
 155  #define __NR_sendmmsg			(__NR_SYSCALL_BASE+374)
 156  #define __NR_setns			(__NR_SYSCALL_BASE+375)
 157  
 158 +#define __NR_LITMUS (__NR_SYSCALL_BASE+376)
 159 +#include <litmus/unistd_32.h>
 160 +
 161  /*
 162   * The following SWIs are ARM private.
 163   */
 164 diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
 165 index 80f7896..ed2ae93 100644
 166 --- a/arch/arm/kernel/calls.S
 167 +++ b/arch/arm/kernel/calls.S
 168 @@ -385,6 +385,18 @@
 169  		CALL(sys_syncfs)
 170  		CALL(sys_sendmmsg)
 171  /* 375 */	CALL(sys_setns)
 172 +		CALL(sys_set_rt_task_param)
 173 +		CALL(sys_get_rt_task_param)
 174 +		CALL(sys_complete_job)
 175 +		CALL(sys_od_open)
 176 +/* 380 */	CALL(sys_od_close)
 177 +		CALL(sys_litmus_lock)
 178 +		CALL(sys_litmus_unlock)
 179 +		CALL(sys_query_job_no)
 180 +		CALL(sys_wait_for_job_release)
 181 +/* 385 */	CALL(sys_wait_for_ts_release)
 182 +		CALL(sys_release_ts)
 183 +		CALL(sys_null_call)
 184  #ifndef syscalls_counted
 185  .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 186  #define syscalls_counted
 187 diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
 188 index e7f92a4..5a57429 100644
 189 --- a/arch/arm/kernel/smp.c
 190 +++ b/arch/arm/kernel/smp.c
 191 @@ -40,6 +40,8 @@
 192  #include <asm/ptrace.h>
 193  #include <asm/localtimer.h>
 194  
 195 +#include <litmus/preempt.h>
 196 +
 197  /*
 198   * as from 2.5, kernels no longer have an init_tasks structure
 199   * so we need some other way of telling a new secondary core
 200 @@ -572,6 +574,8 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 201  		break;
 202  
 203  	case IPI_RESCHEDULE:
 204 +		/* LITMUS^RT: take action based on scheduler state */
 205 +		sched_state_ipi();
 206  		scheduler_ipi();
 207  		break;
 208  
 209 diff --git a/arch/arm/mach-realview/include/mach/timex.h b/arch/arm/mach-realview/include/mach/timex.h
 210 index 4eeb069..e8bcc40 100644
 211 --- a/arch/arm/mach-realview/include/mach/timex.h
 212 +++ b/arch/arm/mach-realview/include/mach/timex.h
 213 @@ -21,3 +21,30 @@
 214   */
 215  
 216  #define CLOCK_TICK_RATE		(50000000 / 16)
 217 +
 218 +#if defined(CONFIG_MACH_REALVIEW_PB11MP) || defined(CONFIG_MACH_REALVIEW_PB1176)
 219 +
 220 +static inline unsigned long realview_get_arm11_cp15_ccnt(void)
 221 +{
 222 +	unsigned long cycles;
 223 +	/* Read CP15 CCNT register. */
 224 +	asm volatile ("mrc p15, 0, %0, c15, c12, 1" : "=r" (cycles));
 225 +	return cycles;
 226 +}
 227 +
 228 +#define get_cycles realview_get_arm11_cp15_ccnt
 229 +
 230 +#elif defined(CONFIG_MACH_REALVIEW_PBA8)
 231 +
 232 +
 233 +static inline unsigned long realview_get_a8_cp15_ccnt(void)
 234 +{
 235 +	unsigned long cycles;
 236 +	/* Read CP15 CCNT register. */
 237 +	asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r" (cycles));
 238 +	return cycles;
 239 +}
 240 +
 241 +#define get_cycles realview_get_a8_cp15_ccnt
 242 +
 243 +#endif
 244 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
 245 index 37357a5..9f5e143 100644
 246 --- a/arch/x86/Kconfig
 247 +++ b/arch/x86/Kconfig
 248 @@ -2166,3 +2166,11 @@ source "crypto/Kconfig"
 249  source "arch/x86/kvm/Kconfig"
 250  
 251  source "lib/Kconfig"
 252 +
 253 +config ARCH_HAS_FEATHER_TRACE
 254 +	def_bool y
 255 +
 256 +config ARCH_HAS_SEND_PULL_TIMERS
 257 +	def_bool y
 258 +
 259 +source "litmus/Kconfig"
 260 diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
 261 index 1cd6d26..3b0d7ef 100644
 262 --- a/arch/x86/include/asm/entry_arch.h
 263 +++ b/arch/x86/include/asm/entry_arch.h
 264 @@ -13,6 +13,7 @@
 265  BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
 266  BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
 267  BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
 268 +BUILD_INTERRUPT(pull_timers_interrupt,PULL_TIMERS_VECTOR)
 269  BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
 270  BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
 271  
 272 diff --git a/arch/x86/include/asm/feather_trace.h b/arch/x86/include/asm/feather_trace.h
 273 new file mode 100644
 274 index 0000000..4fd3163
 275 --- /dev/null
 276 +++ b/arch/x86/include/asm/feather_trace.h
 277 @@ -0,0 +1,17 @@
 278 +#ifndef _ARCH_FEATHER_TRACE_H
 279 +#define _ARCH_FEATHER_TRACE_H
 280 +
 281 +#include <asm/msr.h>
 282 +
 283 +static inline unsigned long long ft_timestamp(void)
 284 +{
 285 +	return __native_read_tsc();
 286 +}
 287 +
 288 +#ifdef CONFIG_X86_32
 289 +#include "feather_trace_32.h"
 290 +#else
 291 +#include "feather_trace_64.h"
 292 +#endif
 293 +
 294 +#endif
 295 diff --git a/arch/x86/include/asm/feather_trace_32.h b/arch/x86/include/asm/feather_trace_32.h
 296 new file mode 100644
 297 index 0000000..70202f9
 298 --- /dev/null
 299 +++ b/arch/x86/include/asm/feather_trace_32.h
 300 @@ -0,0 +1,79 @@
 301 +/* Do not directly include this file. Include feather_trace.h instead */
 302 +
 303 +#define feather_callback __attribute__((regparm(0)))
 304 +
 305 +/*
 306 + * make the compiler reload any register that is not saved in
 307 + * a cdecl function call
 308 + */
 309 +#define CLOBBER_LIST "memory", "cc", "eax", "ecx", "edx"
 310 +
 311 +#define ft_event(id, callback)                                  \
 312 +        __asm__ __volatile__(                                   \
 313 +            "1: jmp 2f                                    \n\t" \
 314 +	    " call " #callback "                          \n\t" \
 315 +            ".section __event_table, \"aw\"               \n\t" \
 316 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 317 +            ".previous                                    \n\t" \
 318 +            "2:                                           \n\t" \
 319 +        : : : CLOBBER_LIST)
 320 +
 321 +#define ft_event0(id, callback)                                 \
 322 +        __asm__ __volatile__(                                   \
 323 +            "1: jmp 2f                                    \n\t" \
 324 +	    " subl $4, %%esp                              \n\t" \
 325 +            " movl $" #id  ", (%%esp)                     \n\t" \
 326 +	    " call " #callback "                          \n\t" \
 327 +	    " addl $4, %%esp                              \n\t" \
 328 +            ".section __event_table, \"aw\"               \n\t" \
 329 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 330 +            ".previous                                    \n\t" \
 331 +            "2:                                           \n\t" \
 332 +        : :  : CLOBBER_LIST)
 333 +
 334 +#define ft_event1(id, callback, param)                          \
 335 +        __asm__ __volatile__(                                   \
 336 +            "1: jmp 2f                                    \n\t" \
 337 +	    " subl $8, %%esp                              \n\t" \
 338 +	    " movl %0, 4(%%esp)                           \n\t" \
 339 +            " movl $" #id  ", (%%esp)                     \n\t" \
 340 +	    " call " #callback "                          \n\t" \
 341 +	    " addl $8, %%esp                              \n\t" \
 342 +            ".section __event_table, \"aw\"               \n\t" \
 343 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 344 +            ".previous                                    \n\t" \
 345 +            "2:                                           \n\t" \
 346 +        : : "r" (param)  : CLOBBER_LIST)
 347 +
 348 +#define ft_event2(id, callback, param, param2)                  \
 349 +        __asm__ __volatile__(                                   \
 350 +            "1: jmp 2f                                    \n\t" \
 351 +	    " subl $12, %%esp                             \n\t" \
 352 +	    " movl %1, 8(%%esp)                           \n\t" \
 353 +	    " movl %0, 4(%%esp)                           \n\t" \
 354 +            " movl $" #id  ", (%%esp)                     \n\t" \
 355 +	    " call " #callback "                          \n\t" \
 356 +	    " addl $12, %%esp                             \n\t" \
 357 +            ".section __event_table, \"aw\"               \n\t" \
 358 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 359 +            ".previous                                    \n\t" \
 360 +            "2:                                           \n\t" \
 361 +        : : "r" (param), "r" (param2)  : CLOBBER_LIST)
 362 +
 363 +
 364 +#define ft_event3(id, callback, p, p2, p3)                      \
 365 +        __asm__ __volatile__(                                   \
 366 +            "1: jmp 2f                                    \n\t" \
 367 +	    " subl $16, %%esp                             \n\t" \
 368 +	    " movl %2, 12(%%esp)                          \n\t" \
 369 +	    " movl %1, 8(%%esp)                           \n\t" \
 370 +	    " movl %0, 4(%%esp)                           \n\t" \
 371 +            " movl $" #id  ", (%%esp)                     \n\t" \
 372 +	    " call " #callback "                          \n\t" \
 373 +	    " addl $16, %%esp                             \n\t" \
 374 +            ".section __event_table, \"aw\"               \n\t" \
 375 +            ".long " #id  ", 0, 1b, 2f                    \n\t" \
 376 +            ".previous                                    \n\t" \
 377 +            "2:                                           \n\t" \
 378 +        : : "r" (p), "r" (p2), "r" (p3)  : CLOBBER_LIST)
 379 +
 380 diff --git a/arch/x86/include/asm/feather_trace_64.h b/arch/x86/include/asm/feather_trace_64.h
 381 new file mode 100644
 382 index 0000000..54ac2ae
 383 --- /dev/null
 384 +++ b/arch/x86/include/asm/feather_trace_64.h
 385 @@ -0,0 +1,67 @@
 386 +/* Do not directly include this file. Include feather_trace.h instead */
 387 +
 388 +/* regparm is the default on x86_64 */
 389 +#define feather_callback
 390 +
 391 +# define _EVENT_TABLE(id,from,to) \
 392 +            ".section __event_table, \"aw\"\n\t" \
 393 +	    ".balign 8\n\t" \
 394 +            ".quad " #id  ", 0, " #from ", " #to " \n\t" \
 395 +            ".previous \n\t"
 396 +
 397 +/*
 398 + * x86_64 callee only owns rbp, rbx, r12 -> r15
 399 + * the called can freely modify the others
 400 + */
 401 +#define CLOBBER_LIST	"memory", "cc", "rdi", "rsi", "rdx", "rcx", \
 402 +			"r8", "r9", "r10", "r11", "rax"
 403 +
 404 +#define ft_event(id, callback)                                  \
 405 +        __asm__ __volatile__(                                   \
 406 +            "1: jmp 2f                                    \n\t" \
 407 +	    " call " #callback "                          \n\t" \
 408 +            _EVENT_TABLE(id,1b,2f) \
 409 +            "2:                                           \n\t" \
 410 +        : : : CLOBBER_LIST)
 411 +
 412 +#define ft_event0(id, callback)                                 \
 413 +        __asm__ __volatile__(                                   \
 414 +            "1: jmp 2f                                    \n\t" \
 415 +	    " movq $" #id ", %%rdi			  \n\t" \
 416 +	    " call " #callback "                          \n\t" \
 417 +	    _EVENT_TABLE(id,1b,2f) \
 418 +            "2:                                           \n\t" \
 419 +        : :  : CLOBBER_LIST)
 420 +
 421 +#define ft_event1(id, callback, param)                          \
 422 +	__asm__ __volatile__(                                   \
 423 +	    "1: jmp 2f                                    \n\t" \
 424 +	    " movq %0, %%rsi				  \n\t"	\
 425 +	    " movq $" #id ", %%rdi			  \n\t" \
 426 +	    " call " #callback "                          \n\t" \
 427 +	    _EVENT_TABLE(id,1b,2f) \
 428 +	    "2:                                           \n\t" \
 429 +	: : "r" (param)  : CLOBBER_LIST)
 430 +
 431 +#define ft_event2(id, callback, param, param2)                  \
 432 +        __asm__ __volatile__(                                   \
 433 +            "1: jmp 2f                                    \n\t" \
 434 +	    " movq %1, %%rdx				  \n\t"	\
 435 +	    " movq %0, %%rsi				  \n\t"	\
 436 +	    " movq $" #id ", %%rdi			  \n\t" \
 437 +	    " call " #callback "                          \n\t" \
 438 +            _EVENT_TABLE(id,1b,2f) \
 439 +            "2:                                           \n\t" \
 440 +        : : "r" (param), "r" (param2)  : CLOBBER_LIST)
 441 +
 442 +#define ft_event3(id, callback, p, p2, p3)                      \
 443 +        __asm__ __volatile__(                                   \
 444 +            "1: jmp 2f                                    \n\t" \
 445 +	    " movq %2, %%rcx				  \n\t"	\
 446 +	    " movq %1, %%rdx				  \n\t"	\
 447 +	    " movq %0, %%rsi				  \n\t"	\
 448 +	    " movq $" #id ", %%rdi			  \n\t" \
 449 +	    " call " #callback "                          \n\t" \
 450 +            _EVENT_TABLE(id,1b,2f) \
 451 +            "2:                                           \n\t" \
 452 +        : : "r" (p), "r" (p2), "r" (p3)  : CLOBBER_LIST)
 453 diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
 454 index bb9efe8..c490d89 100644
 455 --- a/arch/x86/include/asm/hw_irq.h
 456 +++ b/arch/x86/include/asm/hw_irq.h
 457 @@ -77,6 +77,8 @@ extern void threshold_interrupt(void);
 458  extern void call_function_interrupt(void);
 459  extern void call_function_single_interrupt(void);
 460  
 461 +extern void pull_timers_interrupt(void);
 462 +
 463  /* IOAPIC */
 464  #define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs))
 465  extern unsigned long io_apic_irqs;
 466 @@ -155,6 +157,7 @@ extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
 467  extern void smp_reschedule_interrupt(struct pt_regs *);
 468  extern void smp_call_function_interrupt(struct pt_regs *);
 469  extern void smp_call_function_single_interrupt(struct pt_regs *);
 470 +extern void smp_pull_timers_interrupt(struct pt_regs *);
 471  #ifdef CONFIG_X86_32
 472  extern void smp_invalidate_interrupt(struct pt_regs *);
 473  #else
 474 diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
 475 index 6e976ee..99a44cf 100644
 476 --- a/arch/x86/include/asm/irq_vectors.h
 477 +++ b/arch/x86/include/asm/irq_vectors.h
 478 @@ -135,6 +135,13 @@
 479  #define INVALIDATE_TLB_VECTOR_START	\
 480  	(INVALIDATE_TLB_VECTOR_END-NUM_INVALIDATE_TLB_VECTORS+1)
 481  
 482 +/*
 483 + * LITMUS^RT pull timers IRQ vector
 484 + * Make sure it's below the above max 32 vectors.
 485 + */
 486 +#define PULL_TIMERS_VECTOR		0xce
 487 +
 488 +
 489  #define NR_VECTORS			 256
 490  
 491  #define FPU_IRQ				  13
 492 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
 493 index 2193715..b844edc 100644
 494 --- a/arch/x86/include/asm/processor.h
 495 +++ b/arch/x86/include/asm/processor.h
 496 @@ -166,6 +166,10 @@ extern void print_cpu_info(struct cpuinfo_x86 *);
 497  extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 498  extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 499  extern unsigned short num_cache_leaves;
 500 +#ifdef CONFIG_SYSFS
 501 +extern int get_shared_cpu_map(cpumask_var_t mask,
 502 +			       unsigned int cpu, int index);
 503 +#endif
 504  
 505  extern void detect_extended_topology(struct cpuinfo_x86 *c);
 506  extern void detect_ht(struct cpuinfo_x86 *c);
 507 diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
 508 index 593485b..2f6e127 100644
 509 --- a/arch/x86/include/asm/unistd_32.h
 510 +++ b/arch/x86/include/asm/unistd_32.h
 511 @@ -353,9 +353,13 @@
 512  #define __NR_sendmmsg		345
 513  #define __NR_setns		346
 514  
 515 +#define __NR_LITMUS		347
 516 +
 517 +#include "litmus/unistd_32.h"
 518 +
 519  #ifdef __KERNEL__
 520  
 521 -#define NR_syscalls 347
 522 +#define NR_syscalls 347 + NR_litmus_syscalls
 523  
 524  #define __ARCH_WANT_IPC_PARSE_VERSION
 525  #define __ARCH_WANT_OLD_READDIR
 526 diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
 527 index 705bf13..e347f07 100644
 528 --- a/arch/x86/include/asm/unistd_64.h
 529 +++ b/arch/x86/include/asm/unistd_64.h
 530 @@ -682,6 +682,10 @@ __SYSCALL(__NR_sendmmsg, sys_sendmmsg)
 531  #define __NR_setns				308
 532  __SYSCALL(__NR_setns, sys_setns)
 533  
 534 +#define __NR_LITMUS				309
 535 +
 536 +#include "litmus/unistd_64.h"
 537 +
 538  #ifndef __NO_STUBS
 539  #define __ARCH_WANT_OLD_READDIR
 540  #define __ARCH_WANT_OLD_STAT
 541 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
 542 index 90b06d4..d727f8f 100644
 543 --- a/arch/x86/kernel/Makefile
 544 +++ b/arch/x86/kernel/Makefile
 545 @@ -116,6 +116,8 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 546  obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
 547  obj-$(CONFIG_OF)			+= devicetree.o
 548  
 549 +obj-$(CONFIG_FEATHER_TRACE)	+= ft_event.o
 550 +
 551  ###
 552  # 64 bit specific files
 553  ifeq ($(CONFIG_X86_64),y)
 554 diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
 555 index c105c53..0bf1264 100644
 556 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c
 557 +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
 558 @@ -747,6 +747,23 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 559  static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
 560  #define CPUID4_INFO_IDX(x, y)	(&((per_cpu(ici_cpuid4_info, x))[y]))
 561  
 562 +/* returns CPUs that share the index cache with cpu */
 563 +int get_shared_cpu_map(cpumask_var_t mask, unsigned int cpu, int index)
 564 +{
 565 +	int ret = 0;
 566 +	struct _cpuid4_info *this_leaf;
 567 +
 568 +	if (index >= num_cache_leaves) {
 569 +		index = num_cache_leaves - 1;
 570 +		ret = index;
 571 +	}
 572 +
 573 +	this_leaf = CPUID4_INFO_IDX(cpu,index);
 574 +	cpumask_copy(mask, to_cpumask(this_leaf->shared_cpu_map));
 575 +
 576 +	return ret;
 577 +}
 578 +
 579  #ifdef CONFIG_SMP
 580  static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
 581  {
 582 diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
 583 index 8a445a0..47a4bcd 100644
 584 --- a/arch/x86/kernel/entry_64.S
 585 +++ b/arch/x86/kernel/entry_64.S
 586 @@ -1003,6 +1003,8 @@ apicinterrupt CALL_FUNCTION_VECTOR \
 587  	call_function_interrupt smp_call_function_interrupt
 588  apicinterrupt RESCHEDULE_VECTOR \
 589  	reschedule_interrupt smp_reschedule_interrupt
 590 +apicinterrupt PULL_TIMERS_VECTOR \
 591 +	pull_timers_interrupt smp_pull_timers_interrupt
 592  #endif
 593  
 594  apicinterrupt ERROR_APIC_VECTOR \
 595 diff --git a/arch/x86/kernel/ft_event.c b/arch/x86/kernel/ft_event.c
 596 new file mode 100644
 597 index 0000000..37cc332
 598 --- /dev/null
 599 +++ b/arch/x86/kernel/ft_event.c
 600 @@ -0,0 +1,118 @@
 601 +#include <linux/types.h>
 602 +
 603 +#include <litmus/feather_trace.h>
 604 +
 605 +/* the feather trace management functions assume
 606 + * exclusive access to the event table
 607 + */
 608 +
 609 +#ifndef CONFIG_DEBUG_RODATA
 610 +
 611 +#define BYTE_JUMP      0xeb
 612 +#define BYTE_JUMP_LEN  0x02
 613 +
 614 +/* for each event, there is an entry in the event table */
 615 +struct trace_event {
 616 +	long 	id;
 617 +	long	count;
 618 +	long	start_addr;
 619 +	long	end_addr;
 620 +};
 621 +
 622 +extern struct trace_event  __start___event_table[];
 623 +extern struct trace_event  __stop___event_table[];
 624 +
 625 +/* Workaround: if no events are defined, then the event_table section does not
 626 + * exist and the above references cause linker errors. This could probably be
 627 + * fixed by adjusting the linker script, but it is easier to maintain for us if
 628 + * we simply create a dummy symbol in the event table section.
 629 + */
 630 +int __event_table_dummy[0] __attribute__ ((section("__event_table")));
 631 +
 632 +int ft_enable_event(unsigned long id)
 633 +{
 634 +	struct trace_event* te = __start___event_table;
 635 +	int count = 0;
 636 +	char* delta;
 637 +	unsigned char* instr;
 638 +
 639 +	while (te < __stop___event_table) {
 640 +		if (te->id == id && ++te->count == 1) {
 641 +			instr  = (unsigned char*) te->start_addr;
 642 +			/* make sure we don't clobber something wrong */
 643 +			if (*instr == BYTE_JUMP) {
 644 +				delta  = (((unsigned char*) te->start_addr) + 1);
 645 +				*delta = 0;
 646 +			}
 647 +		}
 648 +		if (te->id == id)
 649 +			count++;
 650 +		te++;
 651 +	}
 652 +
 653 +	printk(KERN_DEBUG "ft_enable_event: enabled %d events\n", count);
 654 +	return count;
 655 +}
 656 +
 657 +int ft_disable_event(unsigned long id)
 658 +{
 659 +	struct trace_event* te = __start___event_table;
 660 +	int count = 0;
 661 +	char* delta;
 662 +	unsigned char* instr;
 663 +
 664 +	while (te < __stop___event_table) {
 665 +		if (te->id == id && --te->count == 0) {
 666 +			instr  = (unsigned char*) te->start_addr;
 667 +			if (*instr == BYTE_JUMP) {
 668 +				delta  = (((unsigned char*) te->start_addr) + 1);
 669 +				*delta = te->end_addr - te->start_addr -
 670 +					BYTE_JUMP_LEN;
 671 +			}
 672 +		}
 673 +		if (te->id == id)
 674 +			count++;
 675 +		te++;
 676 +	}
 677 +
 678 +	printk(KERN_DEBUG "ft_disable_event: disabled %d events\n", count);
 679 +	return count;
 680 +}
 681 +
 682 +int ft_disable_all_events(void)
 683 +{
 684 +	struct trace_event* te = __start___event_table;
 685 +	int count = 0;
 686 +	char* delta;
 687 +	unsigned char* instr;
 688 +
 689 +	while (te < __stop___event_table) {
 690 +		if (te->count) {
 691 +			instr  = (unsigned char*) te->start_addr;
 692 +			if (*instr == BYTE_JUMP) {
 693 +				delta  = (((unsigned char*) te->start_addr)
 694 +					  + 1);
 695 +				*delta = te->end_addr - te->start_addr -
 696 +					BYTE_JUMP_LEN;
 697 +				te->count = 0;
 698 +				count++;
 699 +			}
 700 +		}
 701 +		te++;
 702 +	}
 703 +	return count;
 704 +}
 705 +
 706 +int ft_is_event_enabled(unsigned long id)
 707 +{
 708 +	struct trace_event* te = __start___event_table;
 709 +
 710 +	while (te < __stop___event_table) {
 711 +		if (te->id == id)
 712 +			return te->count;
 713 +		te++;
 714 +	}
 715 +	return 0;
 716 +}
 717 +
 718 +#endif
 719 diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
 720 index f470e4e..48acf71 100644
 721 --- a/arch/x86/kernel/irqinit.c
 722 +++ b/arch/x86/kernel/irqinit.c
 723 @@ -252,6 +252,9 @@ static void __init smp_intr_init(void)
 724  	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
 725  			call_function_single_interrupt);
 726  
 727 +	/* IPI for hrtimer pulling on remote cpus */
 728 +	alloc_intr_gate(PULL_TIMERS_VECTOR, pull_timers_interrupt);
 729 +
 730  	/* Low priority IPI to cleanup after moving an irq */
 731  	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
 732  	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
 733 diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
 734 index 013e7eb..ed4c4f5 100644
 735 --- a/arch/x86/kernel/smp.c
 736 +++ b/arch/x86/kernel/smp.c
 737 @@ -23,6 +23,10 @@
 738  #include <linux/cpu.h>
 739  #include <linux/gfp.h>
 740  
 741 +#include <litmus/preempt.h>
 742 +#include <litmus/debug_trace.h>
 743 +#include <litmus/trace.h>
 744 +
 745  #include <asm/mtrr.h>
 746  #include <asm/tlbflush.h>
 747  #include <asm/mmu_context.h>
 748 @@ -118,6 +122,7 @@ static void native_smp_send_reschedule(int cpu)
 749  		WARN_ON(1);
 750  		return;
 751  	}
 752 +	TS_SEND_RESCHED_START(cpu);
 753  	apic->send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
 754  }
 755  
 756 @@ -147,6 +152,16 @@ void native_send_call_func_ipi(const struct cpumask *mask)
 757  	free_cpumask_var(allbutself);
 758  }
 759  
 760 +/* trigger timers on remote cpu */
 761 +void smp_send_pull_timers(int cpu)
 762 +{
 763 +	if (unlikely(cpu_is_offline(cpu))) {
 764 +		WARN_ON(1);
 765 +		return;
 766 +	}
 767 +	apic->send_IPI_mask(cpumask_of(cpu), PULL_TIMERS_VECTOR);
 768 +}
 769 +
 770  /*
 771   * this function calls the 'stop' function on all other CPUs in the system.
 772   */
 773 @@ -199,8 +214,15 @@ static void native_stop_other_cpus(int wait)
 774  void smp_reschedule_interrupt(struct pt_regs *regs)
 775  {
 776  	ack_APIC_irq();
 777 +	/* LITMUS^RT: this IPI might need to trigger the sched state machine. */
 778 +	sched_state_ipi();
 779  	inc_irq_stat(irq_resched_count);
 780 +	/*
 781 +	 * LITMUS^RT: starting from 3.0 schedule_ipi() actually does something.
 782 +	 * This may increase IPI latencies compared with previous versions.
 783 +	 */
 784  	scheduler_ipi();
 785 +	TS_SEND_RESCHED_END;
 786  	/*
 787  	 * KVM uses this interrupt to force a cpu out of guest mode
 788  	 */
 789 @@ -224,6 +246,15 @@ void smp_call_function_single_interrupt(struct pt_regs *regs)
 790  	irq_exit();
 791  }
 792  
 793 +extern void hrtimer_pull(void);
 794 +
 795 +void smp_pull_timers_interrupt(struct pt_regs *regs)
 796 +{
 797 +	ack_APIC_irq();
 798 +	TRACE("pull timer interrupt\n");
 799 +	hrtimer_pull();
 800 +}
 801 +
 802  struct smp_ops smp_ops = {
 803  	.smp_prepare_boot_cpu	= native_smp_prepare_boot_cpu,
 804  	.smp_prepare_cpus	= native_smp_prepare_cpus,
 805 diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
 806 index fbb0a04..d012622 100644
 807 --- a/arch/x86/kernel/syscall_table_32.S
 808 +++ b/arch/x86/kernel/syscall_table_32.S
 809 @@ -346,3 +346,15 @@ ENTRY(sys_call_table)
 810  	.long sys_syncfs
 811  	.long sys_sendmmsg		/* 345 */
 812  	.long sys_setns
 813 +	.long sys_set_rt_task_param	/* LITMUS^RT 347 */
 814 +	.long sys_get_rt_task_param
 815 +	.long sys_complete_job
 816 +	.long sys_od_open
 817 +	.long sys_od_close
 818 +	.long sys_litmus_lock		/* +5 */
 819 +	.long sys_litmus_unlock
 820 +	.long sys_query_job_no
 821 +	.long sys_wait_for_job_release
 822 +	.long sys_wait_for_ts_release
 823 +	.long sys_release_ts		/* +10 */
 824 +	.long sys_null_call
 825 diff --git a/fs/exec.c b/fs/exec.c
 826 index 6075a1e..9984562 100644
 827 --- a/fs/exec.c
 828 +++ b/fs/exec.c
 829 @@ -19,7 +19,7 @@
 830   * current->executable is only used by the procfs.  This allows a dispatch
 831   * table to check for several different types  of binary formats.  We keep
 832   * trying until we recognize the file or we run out of supported binary
 833 - * formats. 
 834 + * formats.
 835   */
 836  
 837  #include <linux/slab.h>
 838 @@ -56,6 +56,8 @@
 839  #include <linux/oom.h>
 840  #include <linux/compat.h>
 841  
 842 +#include <litmus/litmus.h>
 843 +
 844  #include <asm/uaccess.h>
 845  #include <asm/mmu_context.h>
 846  #include <asm/tlb.h>
 847 @@ -85,7 +87,7 @@ int __register_binfmt(struct linux_binfmt * fmt, int insert)
 848  	insert ? list_add(&fmt->lh, &formats) :
 849  		 list_add_tail(&fmt->lh, &formats);
 850  	write_unlock(&binfmt_lock);
 851 -	return 0;	
 852 +	return 0;
 853  }
 854  
 855  EXPORT_SYMBOL(__register_binfmt);
 856 @@ -1160,7 +1162,7 @@ void setup_new_exec(struct linux_binprm * bprm)
 857  	   group */
 858  
 859  	current->self_exec_id++;
 860 -			
 861 +
 862  	flush_signal_handlers(current, 0);
 863  	flush_old_files(current->files);
 864  }
 865 @@ -1250,8 +1252,8 @@ int check_unsafe_exec(struct linux_binprm *bprm)
 866  	return res;
 867  }
 868  
 869 -/* 
 870 - * Fill the binprm structure from the inode. 
 871 +/*
 872 + * Fill the binprm structure from the inode.
 873   * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
 874   *
 875   * This may be called multiple times for binary chains (scripts for example).
 876 @@ -1459,6 +1461,7 @@ static int do_execve_common(const char *filename,
 877  		goto out_unmark;
 878  
 879  	sched_exec();
 880 +	litmus_exec();
 881  
 882  	bprm->file = file;
 883  	bprm->filename = filename;
 884 diff --git a/fs/inode.c b/fs/inode.c
 885 index 43566d1..dbf0e76 100644
 886 --- a/fs/inode.c
 887 +++ b/fs/inode.c
 888 @@ -308,6 +308,8 @@ void inode_init_once(struct inode *inode)
 889  #ifdef CONFIG_FSNOTIFY
 890  	INIT_HLIST_HEAD(&inode->i_fsnotify_marks);
 891  #endif
 892 +	INIT_LIST_HEAD(&inode->i_obj_list);
 893 +	mutex_init(&inode->i_obj_mutex);
 894  }
 895  EXPORT_SYMBOL(inode_init_once);
 896  
 897 diff --git a/include/linux/completion.h b/include/linux/completion.h
 898 index 51494e6..9d72727 100644
 899 --- a/include/linux/completion.h
 900 +++ b/include/linux/completion.h
 901 @@ -90,6 +90,7 @@ extern bool completion_done(struct completion *x);
 902  
 903  extern void complete(struct completion *);
 904  extern void complete_all(struct completion *);
 905 +extern void complete_n(struct completion *, int n);
 906  
 907  /**
 908   * INIT_COMPLETION - reinitialize a completion structure
 909 diff --git a/include/linux/fs.h b/include/linux/fs.h
 910 index b5b9792..8d5834b 100644
 911 --- a/include/linux/fs.h
 912 +++ b/include/linux/fs.h
 913 @@ -17,8 +17,8 @@
 914   * nr_file rlimit, so it's safe to set up a ridiculously high absolute
 915   * upper limit on files-per-process.
 916   *
 917 - * Some programs (notably those using select()) may have to be 
 918 - * recompiled to take full advantage of the new limits..  
 919 + * Some programs (notably those using select()) may have to be
 920 + * recompiled to take full advantage of the new limits..
 921   */
 922  
 923  /* Fixed constants first: */
 924 @@ -172,7 +172,7 @@ struct inodes_stat_t {
 925  #define SEL_EX		4
 926  
 927  /* public flags for file_system_type */
 928 -#define FS_REQUIRES_DEV 1 
 929 +#define FS_REQUIRES_DEV 1
 930  #define FS_BINARY_MOUNTDATA 2
 931  #define FS_HAS_SUBTYPE 4
 932  #define FS_REVAL_DOT	16384	/* Check the paths ".", ".." for staleness */
 933 @@ -480,7 +480,7 @@ struct iattr {
 934   */
 935  #include <linux/quota.h>
 936  
 937 -/** 
 938 +/**
 939   * enum positive_aop_returns - aop return codes with specific semantics
 940   *
 941   * @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has
 942 @@ -490,7 +490,7 @@ struct iattr {
 943   * 			    be a candidate for writeback again in the near
 944   * 			    future.  Other callers must be careful to unlock
 945   * 			    the page if they get this return.  Returned by
 946 - * 			    writepage(); 
 947 + * 			    writepage();
 948   *
 949   * @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has
 950   *  			unlocked it and the page might have been truncated.
 951 @@ -734,6 +734,7 @@ static inline int mapping_writably_mapped(struct address_space *mapping)
 952  
 953  struct posix_acl;
 954  #define ACL_NOT_CACHED ((void *)(-1))
 955 +struct inode_obj_id_table;
 956  
 957  struct inode {
 958  	/* RCU path lookup touches following: */
 959 @@ -807,6 +808,8 @@ struct inode {
 960  	struct posix_acl	*i_acl;
 961  	struct posix_acl	*i_default_acl;
 962  #endif
 963 +	struct list_head	i_obj_list;
 964 +	struct mutex		i_obj_mutex;
 965  	void			*i_private; /* fs or device private pointer */
 966  };
 967  
 968 @@ -1032,10 +1035,10 @@ static inline int file_check_writeable(struct file *filp)
 969  
 970  #define	MAX_NON_LFS	((1UL<<31) - 1)
 971  
 972 -/* Page cache limit. The filesystems should put that into their s_maxbytes 
 973 -   limits, otherwise bad things can happen in VM. */ 
 974 +/* Page cache limit. The filesystems should put that into their s_maxbytes
 975 +   limits, otherwise bad things can happen in VM. */
 976  #if BITS_PER_LONG==32
 977 -#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) 
 978 +#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
 979  #elif BITS_PER_LONG==64
 980  #define MAX_LFS_FILESIZE 	0x7fffffffffffffffUL
 981  #endif
 982 @@ -2234,7 +2237,7 @@ extern void free_write_pipe(struct file *);
 983  
 984  extern int kernel_read(struct file *, loff_t, char *, unsigned long);
 985  extern struct file * open_exec(const char *);
 986 - 
 987 +
 988  /* fs/dcache.c -- generic fs support functions */
 989  extern int is_subdir(struct dentry *, struct dentry *);
 990  extern int path_is_under(struct path *, struct path *);
 991 diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
 992 index ba36217..e6dd5a4 100644
 993 --- a/include/linux/hardirq.h
 994 +++ b/include/linux/hardirq.h
 995 @@ -6,6 +6,8 @@
 996  #include <linux/ftrace_irq.h>
 997  #include <asm/hardirq.h>
 998  
 999 +#include <litmus/trace_irq.h>
1000 +
1001  /*
1002   * We put the hardirq and softirq counter into the preemption
1003   * counter. The bitmask has the following meaning:
1004 @@ -186,6 +188,7 @@ extern void rcu_nmi_exit(void);
1005  		account_system_vtime(current);		\
1006  		add_preempt_count(HARDIRQ_OFFSET);	\
1007  		trace_hardirq_enter();			\
1008 +		ft_irq_fired();				\
1009  	} while (0)
1010  
1011  /*
1012 @@ -216,6 +219,7 @@ extern void irq_exit(void);
1013  		lockdep_off();					\
1014  		rcu_nmi_enter();				\
1015  		trace_hardirq_enter();				\
1016 +		ft_irq_fired();					\
1017  	} while (0)
1018  
1019  #define nmi_exit()						\
1020 diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
1021 index fd0dc30..d91bba5 100644
1022 --- a/include/linux/hrtimer.h
1023 +++ b/include/linux/hrtimer.h
1024 @@ -174,6 +174,7 @@ enum  hrtimer_base_type {
1025   * @nr_hangs:		Total number of hrtimer interrupt hangs
1026   * @max_hang_time:	Maximum time spent in hrtimer_interrupt
1027   * @clock_base:		array of clock bases for this cpu
1028 + * @to_pull:		LITMUS^RT list of timers to be pulled on this cpu
1029   */
1030  struct hrtimer_cpu_base {
1031  	raw_spinlock_t			lock;
1032 @@ -188,8 +189,32 @@ struct hrtimer_cpu_base {
1033  	ktime_t				max_hang_time;
1034  #endif
1035  	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
1036 +	struct list_head		to_pull;
1037  };
1038  
1039 +#ifdef CONFIG_ARCH_HAS_SEND_PULL_TIMERS
1040 +
1041 +#define HRTIMER_START_ON_INACTIVE	0
1042 +#define HRTIMER_START_ON_QUEUED		1
1043 +
1044 +/*
1045 + * struct hrtimer_start_on_info - save timer info on remote cpu
1046 + * @list:	list of hrtimer_start_on_info on remote cpu (to_pull)
1047 + * @timer:	timer to be triggered on remote cpu
1048 + * @time:	time event
1049 + * @mode:	timer mode
1050 + * @state:	activity flag
1051 + */
1052 +struct hrtimer_start_on_info {
1053 +	struct list_head	list;
1054 +	struct hrtimer		*timer;
1055 +	ktime_t			time;
1056 +	enum hrtimer_mode	mode;
1057 +	atomic_t		state;
1058 +};
1059 +
1060 +#endif
1061 +
1062  static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
1063  {
1064  	timer->node.expires = time;
1065 @@ -355,6 +380,13 @@ __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
1066  			 unsigned long delta_ns,
1067  			 const enum hrtimer_mode mode, int wakeup);
1068  
1069 +#ifdef CONFIG_ARCH_HAS_SEND_PULL_TIMERS
1070 +extern void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info);
1071 +extern int hrtimer_start_on(int cpu, struct hrtimer_start_on_info *info,
1072 +			struct hrtimer *timer, ktime_t time,
1073 +			const enum hrtimer_mode mode);
1074 +#endif
1075 +
1076  extern int hrtimer_cancel(struct hrtimer *timer);
1077  extern int hrtimer_try_to_cancel(struct hrtimer *timer);
1078  
1079 diff --git a/include/linux/sched.h b/include/linux/sched.h
1080 index 14a6c7b..9c990d1 100644
1081 --- a/include/linux/sched.h
1082 +++ b/include/linux/sched.h
1083 @@ -39,6 +39,7 @@
1084  #define SCHED_BATCH		3
1085  /* SCHED_ISO: reserved but not implemented yet */
1086  #define SCHED_IDLE		5
1087 +#define SCHED_LITMUS		6
1088  /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
1089  #define SCHED_RESET_ON_FORK     0x40000000
1090  
1091 @@ -93,6 +94,9 @@ struct sched_param {
1092  
1093  #include <asm/processor.h>
1094  
1095 +#include <litmus/rt_param.h>
1096 +#include <litmus/preempt.h>
1097 +
1098  struct exec_domain;
1099  struct futex_pi_state;
1100  struct robust_list_head;
1101 @@ -1209,6 +1213,7 @@ struct sched_rt_entity {
1102  };
1103  
1104  struct rcu_node;
1105 +struct od_table_entry;
1106  
1107  enum perf_event_task_context {
1108  	perf_invalid_context = -1,
1109 @@ -1313,9 +1318,9 @@ struct task_struct {
1110  	unsigned long stack_canary;
1111  #endif
1112  
1113 -	/* 
1114 +	/*
1115  	 * pointers to (original) parent process, youngest child, younger sibling,
1116 -	 * older sibling, respectively.  (p->father can be replaced with 
1117 +	 * older sibling, respectively.  (p->father can be replaced with
1118  	 * p->real_parent->pid)
1119  	 */
1120  	struct task_struct *real_parent; /* real parent process */
1121 @@ -1526,6 +1531,13 @@ struct task_struct {
1122  	int make_it_fail;
1123  #endif
1124  	struct prop_local_single dirties;
1125 +
1126 +	/* LITMUS RT parameters and state */
1127 +	struct rt_param rt_param;
1128 +
1129 +	/* references to PI semaphores, etc. */
1130 +	struct od_table_entry *od_table;
1131 +
1132  #ifdef CONFIG_LATENCYTOP
1133  	int latency_record_count;
1134  	struct latency_record latency_record[LT_SAVECOUNT];
1135 @@ -2136,7 +2148,7 @@ static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, s
1136  	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
1137  
1138  	return ret;
1139 -}	
1140 +}
1141  
1142  extern void block_all_signals(int (*notifier)(void *priv), void *priv,
1143  			      sigset_t *mask);
1144 @@ -2446,6 +2458,7 @@ static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag)
1145  static inline void set_tsk_need_resched(struct task_struct *tsk)
1146  {
1147  	set_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
1148 +	sched_state_will_schedule(tsk);
1149  }
1150  
1151  static inline void clear_tsk_need_resched(struct task_struct *tsk)
1152 diff --git a/include/linux/smp.h b/include/linux/smp.h
1153 index 8cc38d3..53b1bee 100644
1154 --- a/include/linux/smp.h
1155 +++ b/include/linux/smp.h
1156 @@ -82,6 +82,11 @@ int smp_call_function_any(const struct cpumask *mask,
1157  			  smp_call_func_t func, void *info, int wait);
1158  
1159  /*
1160 + * sends a 'pull timer' event to a remote CPU
1161 + */
1162 +extern void smp_send_pull_timers(int cpu);
1163 +
1164 +/*
1165   * Generic and arch helpers
1166   */
1167  #ifdef CONFIG_USE_GENERIC_SMP_HELPERS
1168 diff --git a/include/linux/tick.h b/include/linux/tick.h
1169 index b232ccc..1e29bd5 100644
1170 --- a/include/linux/tick.h
1171 +++ b/include/linux/tick.h
1172 @@ -74,6 +74,11 @@ extern int tick_is_oneshot_available(void);
1173  extern struct tick_device *tick_get_device(int cpu);
1174  
1175  # ifdef CONFIG_HIGH_RES_TIMERS
1176 +/* LITMUS^RT tick alignment */
1177 +#define LINUX_DEFAULT_TICKS	0
1178 +#define LITMUS_ALIGNED_TICKS	1
1179 +#define	LITMUS_STAGGERED_TICKS	2
1180 +
1181  extern int tick_init_highres(void);
1182  extern int tick_program_event(ktime_t expires, int force);
1183  extern void tick_setup_sched_timer(void);
1184 diff --git a/include/litmus/affinity.h b/include/litmus/affinity.h
1185 new file mode 100644
1186 index 0000000..ca2e442
1187 --- /dev/null
1188 +++ b/include/litmus/affinity.h
1189 @@ -0,0 +1,80 @@
1190 +#ifndef __LITMUS_AFFINITY_H
1191 +#define __LITMUS_AFFINITY_H
1192 +
1193 +#include <linux/cpumask.h>
1194 +
1195 +/*
1196 +  L1 (instr) = depth 0
1197 +  L1 (data)  = depth 1
1198 +  L2 = depth 2
1199 +  L3 = depth 3
1200 + */
1201 +#define NUM_CACHE_LEVELS 4
1202 +
1203 +struct neighborhood
1204 +{
1205 +	unsigned int size[NUM_CACHE_LEVELS];
1206 +	cpumask_var_t neighbors[NUM_CACHE_LEVELS];
1207 +};
1208 +
1209 +/* topology info is stored redundently in a big array for fast lookups */
1210 +extern struct neighborhood neigh_info[NR_CPUS];
1211 +
1212 +void init_topology(void); /* called by Litmus module's _init_litmus() */
1213 +
1214 +/* Works like:
1215 +void get_nearest_available_cpu(
1216 +	cpu_entry_t **nearest,
1217 +	cpu_entry_t *start,
1218 +	cpu_entry_t *entries,
1219 +	int release_master)
1220 +
1221 +Set release_master = NO_CPU for no Release Master.
1222 +
1223 +We use a macro here to exploit the fact that C-EDF and G-EDF
1224 +have similar structures for their cpu_entry_t structs, even though
1225 +they do not share a common base-struct.  The macro allows us to
1226 +avoid code duplication.
1227 +
1228 +TODO: Factor out the job-to-processor linking from C/G-EDF into
1229 +a reusable "processor mapping".  (See B.B.'s RTSS'09 paper &
1230 +dissertation.)
1231 + */
1232 +#define get_nearest_available_cpu(nearest, start, entries, release_master) \
1233 +{ \
1234 +	(nearest) = NULL; \
1235 +	if (!(start)->linked) { \
1236 +		(nearest) = (start); \
1237 +	} else { \
1238 +		int __level; \
1239 +		int __cpu; \
1240 +		int __release_master = ((release_master) == NO_CPU) ? -1 : (release_master); \
1241 +		struct neighborhood *__neighbors = &neigh_info[(start)->cpu]; \
1242 +		\
1243 +		for (__level = 0; (__level < NUM_CACHE_LEVELS) && !(nearest); ++__level) { \
1244 +			if (__neighbors->size[__level] > 1) { \
1245 +				for_each_cpu(__cpu, __neighbors->neighbors[__level]) { \
1246 +					if (__cpu != __release_master) { \
1247 +						cpu_entry_t *__entry = &per_cpu((entries), __cpu); \
1248 +						if (!__entry->linked) { \
1249 +							(nearest) = __entry; \
1250 +							break; \
1251 +						} \
1252 +					} \
1253 +				} \
1254 +			} else if (__neighbors->size[__level] == 0) { \
1255 +				break; \
1256 +			} \
1257 +		} \
1258 +	} \
1259 +	\
1260 +	if ((nearest)) { \
1261 +		TRACE("P%d is closest available CPU to P%d\n", \
1262 +				(nearest)->cpu, (start)->cpu); \
1263 +	} else { \
1264 +		TRACE("Could not find an available CPU close to P%d\n", \
1265 +				(start)->cpu); \
1266 +	} \
1267 +}
1268 +
1269 +#endif
1270 diff --git a/include/litmus/bheap.h b/include/litmus/bheap.h
1271 new file mode 100644
1272 index 0000000..cf4864a
1273 --- /dev/null
1274 +++ b/include/litmus/bheap.h
1275 @@ -0,0 +1,77 @@
1276 +/* bheaps.h -- Binomial Heaps
1277 + *
1278 + * (c) 2008, 2009 Bjoern Brandenburg
1279 + */
1280 +
1281 +#ifndef BHEAP_H
1282 +#define BHEAP_H
1283 +
1284 +#define NOT_IN_HEAP UINT_MAX
1285 +
1286 +struct bheap_node {
1287 +	struct bheap_node* 	parent;
1288 +	struct bheap_node* 	next;
1289 +	struct bheap_node* 	child;
1290 +
1291 +	unsigned int 		degree;
1292 +	void*			value;
1293 +	struct bheap_node**	ref;
1294 +};
1295 +
1296 +struct bheap {
1297 +	struct bheap_node* 	head;
1298 +	/* We cache the minimum of the heap.
1299 +	 * This speeds up repeated peek operations.
1300 +	 */
1301 +	struct bheap_node*	min;
1302 +};
1303 +
1304 +typedef int (*bheap_prio_t)(struct bheap_node* a, struct bheap_node* b);
1305 +
1306 +void bheap_init(struct bheap* heap);
1307 +void bheap_node_init(struct bheap_node** ref_to_bheap_node_ptr, void* value);
1308 +
1309 +static inline int bheap_node_in_heap(struct bheap_node* h)
1310 +{
1311 +	return h->degree != NOT_IN_HEAP;
1312 +}
1313 +
1314 +static inline int bheap_empty(struct bheap* heap)
1315 +{
1316 +	return heap->head == NULL && heap->min == NULL;
1317 +}
1318 +
1319 +/* insert (and reinitialize) a node into the heap */
1320 +void bheap_insert(bheap_prio_t higher_prio,
1321 +		 struct bheap* heap,
1322 +		 struct bheap_node* node);
1323 +
1324 +/* merge addition into target */
1325 +void bheap_union(bheap_prio_t higher_prio,
1326 +		struct bheap* target,
1327 +		struct bheap* addition);
1328 +
1329 +struct bheap_node* bheap_peek(bheap_prio_t higher_prio,
1330 +			    struct bheap* heap);
1331 +
1332 +struct bheap_node* bheap_take(bheap_prio_t higher_prio,
1333 +			    struct bheap* heap);
1334 +
1335 +void bheap_uncache_min(bheap_prio_t higher_prio, struct bheap* heap);
1336 +int  bheap_decrease(bheap_prio_t higher_prio, struct bheap_node* node);
1337 +
1338 +void bheap_delete(bheap_prio_t higher_prio,
1339 +		 struct bheap* heap,
1340 +		 struct bheap_node* node);
1341 +
1342 +/* allocate from memcache */
1343 +struct bheap_node* bheap_node_alloc(int gfp_flags);
1344 +void bheap_node_free(struct bheap_node* hn);
1345 +
1346 +/* allocate a heap node for value and insert into the heap */
1347 +int bheap_add(bheap_prio_t higher_prio, struct bheap* heap,
1348 +	     void* value, int gfp_flags);
1349 +
1350 +void* bheap_take_del(bheap_prio_t higher_prio,
1351 +		    struct bheap* heap);
1352 +#endif
1353 diff --git a/include/litmus/budget.h b/include/litmus/budget.h
1354 new file mode 100644
1355 index 0000000..732530e
1356 --- /dev/null
1357 +++ b/include/litmus/budget.h
1358 @@ -0,0 +1,8 @@
1359 +#ifndef _LITMUS_BUDGET_H_
1360 +#define _LITMUS_BUDGET_H_
1361 +
1362 +/* Update the per-processor enforcement timer (arm/reproram/cancel) for
1363 + * the next task. */
1364 +void update_enforcement_timer(struct task_struct* t);
1365 +
1366 +#endif
1367 diff --git a/include/litmus/clustered.h b/include/litmus/clustered.h
1368 new file mode 100644
1369 index 0000000..0c18dcb
1370 --- /dev/null
1371 +++ b/include/litmus/clustered.h
1372 @@ -0,0 +1,44 @@
1373 +#ifndef CLUSTERED_H
1374 +#define CLUSTERED_H
1375 +
1376 +/* Which cache level should be used to group CPUs into clusters?
1377 + * GLOBAL_CLUSTER means that all CPUs form a single cluster (just like under
1378 + * global scheduling).
1379 + */
1380 +enum cache_level {
1381 +	GLOBAL_CLUSTER = 0,
1382 +	L1_CLUSTER     = 1,
1383 +	L2_CLUSTER     = 2,
1384 +	L3_CLUSTER     = 3
1385 +};
1386 +
1387 +int parse_cache_level(const char *str, enum cache_level *level);
1388 +const char* cache_level_name(enum cache_level level);
1389 +
1390 +/* expose a cache level in a /proc dir */
1391 +struct proc_dir_entry* create_cluster_file(struct proc_dir_entry* parent,
1392 +					   enum cache_level* level);
1393 +
1394 +
1395 +
1396 +struct scheduling_cluster {
1397 +	unsigned int id;
1398 +	/* list of CPUs that are part of this cluster */
1399 +	struct list_head cpus;
1400 +};
1401 +
1402 +struct cluster_cpu {
1403 +	unsigned int id; /* which CPU is this? */
1404 +	struct list_head cluster_list; /* List of the CPUs in this cluster. */
1405 +	struct scheduling_cluster* cluster; /* The cluster that this CPU belongs to. */
1406 +};
1407 +
1408 +int get_cluster_size(enum cache_level level);
1409 +
1410 +int assign_cpus_to_clusters(enum cache_level level,
1411 +			    struct scheduling_cluster* clusters[],
1412 +			    unsigned int num_clusters,
1413 +			    struct cluster_cpu* cpus[],
1414 +			    unsigned int num_cpus);
1415 +
1416 +#endif
1417 diff --git a/include/litmus/debug_trace.h b/include/litmus/debug_trace.h
1418 new file mode 100644
1419 index 0000000..48d086d
1420 --- /dev/null
1421 +++ b/include/litmus/debug_trace.h
1422 @@ -0,0 +1,37 @@
1423 +#ifndef LITMUS_DEBUG_TRACE_H
1424 +#define LITMUS_DEBUG_TRACE_H
1425 +
1426 +#ifdef CONFIG_SCHED_DEBUG_TRACE
1427 +void sched_trace_log_message(const char* fmt, ...);
1428 +void dump_trace_buffer(int max);
1429 +#else
1430 +
1431 +#define sched_trace_log_message(fmt, ...)
1432 +
1433 +#endif
1434 +
1435 +extern atomic_t __log_seq_no;
1436 +
1437 +#ifdef CONFIG_SCHED_DEBUG_TRACE_CALLER
1438 +#define TRACE_PREFIX "%d P%d [%s@%s:%d]: "
1439 +#define TRACE_ARGS  atomic_add_return(1, &__log_seq_no),	\
1440 +		raw_smp_processor_id(),				\
1441 +		__FUNCTION__, __FILE__, __LINE__
1442 +#else
1443 +#define TRACE_PREFIX "%d P%d: "
1444 +#define TRACE_ARGS  atomic_add_return(1, &__log_seq_no), \
1445 +		raw_smp_processor_id()
1446 +#endif
1447 +
1448 +#define TRACE(fmt, args...)						\
1449 +	sched_trace_log_message(TRACE_PREFIX fmt,			\
1450 +				TRACE_ARGS,  ## args)
1451 +
1452 +#define TRACE_TASK(t, fmt, args...)			\
1453 +	TRACE("(%s/%d:%d) " fmt, (t)->comm, (t)->pid,	\
1454 +	      (t)->rt_param.job_params.job_no,  ##args)
1455 +
1456 +#define TRACE_CUR(fmt, args...) \
1457 +	TRACE_TASK(current, fmt, ## args)
1458 +
1459 +#endif
1460 diff --git a/include/litmus/edf_common.h b/include/litmus/edf_common.h
1461 new file mode 100644
1462 index 0000000..bbaf22e
1463 --- /dev/null
1464 +++ b/include/litmus/edf_common.h
1465 @@ -0,0 +1,25 @@
1466 +/*
1467 + * EDF common data structures and utility functions shared by all EDF
1468 + * based scheduler plugins
1469 + */
1470 +
1471 +/* CLEANUP: Add comments and make it less messy.
1472 + *
1473 + */
1474 +
1475 +#ifndef __UNC_EDF_COMMON_H__
1476 +#define __UNC_EDF_COMMON_H__
1477 +
1478 +#include <litmus/rt_domain.h>
1479 +
1480 +void edf_domain_init(rt_domain_t* rt, check_resched_needed_t resched,
1481 +		     release_jobs_t release);
1482 +
1483 +int edf_higher_prio(struct task_struct* first,
1484 +		    struct task_struct* second);
1485 +
1486 +int edf_ready_order(struct bheap_node* a, struct bheap_node* b);
1487 +
1488 +int edf_preemption_needed(rt_domain_t* rt, struct task_struct *t);
1489 +
1490 +#endif
1491 diff --git a/include/litmus/fdso.h b/include/litmus/fdso.h
1492 new file mode 100644
1493 index 0000000..caf2a1e
1494 --- /dev/null
1495 +++ b/include/litmus/fdso.h
1496 @@ -0,0 +1,71 @@
1497 +/* fdso.h - file descriptor attached shared objects
1498 + *
1499 + * (c) 2007 B. Brandenburg, LITMUS^RT project
1500 + */
1501 +
1502 +#ifndef _LINUX_FDSO_H_
1503 +#define _LINUX_FDSO_H_
1504 +
1505 +#include <linux/list.h>
1506 +#include <asm/atomic.h>
1507 +
1508 +#include <linux/fs.h>
1509 +#include <linux/slab.h>
1510 +
1511 +#define MAX_OBJECT_DESCRIPTORS 32
1512 +
1513 +typedef enum  {
1514 +	MIN_OBJ_TYPE 	= 0,
1515 +
1516 +	FMLP_SEM	= 0,
1517 +	SRP_SEM		= 1,
1518 +
1519 +	MAX_OBJ_TYPE	= 1
1520 +} obj_type_t;
1521 +
1522 +struct inode_obj_id {
1523 +	struct list_head	list;
1524 +	atomic_t		count;
1525 +	struct inode*		inode;
1526 +
1527 +	obj_type_t 		type;
1528 +	void*			obj;
1529 +	unsigned int		id;
1530 +};
1531 +
1532 +struct fdso_ops;
1533 +
1534 +struct od_table_entry {
1535 +	unsigned int		used;
1536 +
1537 +	struct inode_obj_id*	obj;
1538 +	const struct fdso_ops*	class;
1539 +};
1540 +
1541 +struct fdso_ops {
1542 +	int   (*create)(void** obj_ref, obj_type_t type, void* __user);
1543 +	void  (*destroy)(obj_type_t type, void*);
1544 +	int   (*open)	(struct od_table_entry*, void* __user);
1545 +	int   (*close)	(struct od_table_entry*);
1546 +};
1547 +
1548 +/* translate a userspace supplied od into the raw table entry
1549 + * returns NULL if od is invalid
1550 + */
1551 +struct od_table_entry* get_entry_for_od(int od);
1552 +
1553 +/* translate a userspace supplied od into the associated object
1554 + * returns NULL if od is invalid
1555 + */
1556 +static inline void* od_lookup(int od, obj_type_t type)
1557 +{
1558 +	struct od_table_entry* e = get_entry_for_od(od);
1559 +	return e && e->obj->type == type ? e->obj->obj : NULL;
1560 +}
1561 +
1562 +#define lookup_fmlp_sem(od)((struct pi_semaphore*)  od_lookup(od, FMLP_SEM))
1563 +#define lookup_srp_sem(od) ((struct srp_semaphore*) od_lookup(od, SRP_SEM))
1564 +#define lookup_ics(od)     ((struct ics*)           od_lookup(od, ICS_ID))
1565 +
1566 +
1567 +#endif
1568 diff --git a/include/litmus/feather_buffer.h b/include/litmus/feather_buffer.h
1569 new file mode 100644
1570 index 0000000..6c18277
1571 --- /dev/null
1572 +++ b/include/litmus/feather_buffer.h
1573 @@ -0,0 +1,94 @@
1574 +#ifndef _FEATHER_BUFFER_H_
1575 +#define _FEATHER_BUFFER_H_
1576 +
1577 +/* requires UINT_MAX and memcpy */
1578 +
1579 +#define SLOT_FREE	0
1580 +#define	SLOT_BUSY 	1
1581 +#define	SLOT_READY	2
1582 +
1583 +struct ft_buffer {
1584 +	unsigned int	slot_count;
1585 +	unsigned int	slot_size;
1586 +
1587 +	int 		free_count;
1588 +	unsigned int 	write_idx;
1589 +	unsigned int 	read_idx;
1590 +
1591 +	char*		slots;
1592 +	void*		buffer_mem;
1593 +	unsigned int	failed_writes;
1594 +};
1595 +
1596 +static inline int init_ft_buffer(struct ft_buffer*	buf,
1597 +				 unsigned int 		slot_count,
1598 +				 unsigned int 		slot_size,
1599 +				 char*			slots,
1600 +				 void* 			buffer_mem)
1601 +{
1602 +	int i = 0;
1603 +	if (!slot_count || UINT_MAX % slot_count != slot_count - 1) {
1604 +		/* The slot count must divide UNIT_MAX + 1 so that when it
1605 +		 * wraps around the index correctly points to 0.
1606 +		 */
1607 +		return 0;
1608 +	} else {
1609 +		buf->slot_count    = slot_count;
1610 +		buf->slot_size     = slot_size;
1611 +		buf->slots         = slots;
1612 +		buf->buffer_mem    = buffer_mem;
1613 +		buf->free_count    = slot_count;
1614 +		buf->write_idx     = 0;
1615 +		buf->read_idx      = 0;
1616 +		buf->failed_writes = 0;
1617 +		for (i = 0; i < slot_count; i++)
1618 +			buf->slots[i] = SLOT_FREE;
1619 +		return 1;
1620 +	}
1621 +}
1622 +
1623 +static inline int ft_buffer_start_write(struct ft_buffer* buf, void **ptr)
1624 +{
1625 +	int free = fetch_and_dec(&buf->free_count);
1626 +	unsigned int idx;
1627 +	if (free <= 0) {
1628 +		fetch_and_inc(&buf->free_count);
1629 +		*ptr = 0;
1630 +		fetch_and_inc(&buf->failed_writes);
1631 +		return 0;
1632 +	} else {
1633 +		idx  = fetch_and_inc((int*) &buf->write_idx) % buf->slot_count;
1634 +		buf->slots[idx] = SLOT_BUSY;
1635 +		*ptr = ((char*) buf->buffer_mem) + idx * buf->slot_size;
1636 +		return 1;
1637 +	}
1638 +}
1639 +
1640 +static inline void ft_buffer_finish_write(struct ft_buffer* buf, void *ptr)
1641 +{
1642 +	unsigned int idx = ((char*) ptr - (char*) buf->buffer_mem) / buf->slot_size;
1643 +	buf->slots[idx]  = SLOT_READY;
1644 +}
1645 +
1646 +
1647 +/* exclusive reader access is assumed */
1648 +static inline int ft_buffer_read(struct ft_buffer* buf, void* dest)
1649 +{
1650 +	unsigned int idx;
1651 +	if (buf->free_count == buf->slot_count)
1652 +		/* nothing available */
1653 +		return 0;
1654 +	idx = buf->read_idx % buf->slot_count;
1655 +	if (buf->slots[idx] == SLOT_READY) {
1656 +		memcpy(dest, ((char*) buf->buffer_mem) + idx * buf->slot_size,
1657 +		       buf->slot_size);
1658 +		buf->slots[idx] = SLOT_FREE;
1659 +		buf->read_idx++;
1660 +		fetch_and_inc(&buf->free_count);
1661 +		return 1;
1662 +	} else
1663 +		return 0;
1664 +}
1665 +
1666 +
1667 +#endif
1668 diff --git a/include/litmus/feather_trace.h b/include/litmus/feather_trace.h
1669 new file mode 100644
1670 index 0000000..028dfb2
1671 --- /dev/null
1672 +++ b/include/litmus/feather_trace.h
1673 @@ -0,0 +1,65 @@
1674 +#ifndef _FEATHER_TRACE_H_
1675 +#define _FEATHER_TRACE_H_
1676 +
1677 +#include <asm/atomic.h>
1678 +
1679 +int ft_enable_event(unsigned long id);
1680 +int ft_disable_event(unsigned long id);
1681 +int ft_is_event_enabled(unsigned long id);
1682 +int ft_disable_all_events(void);
1683 +
1684 +/* atomic_* funcitons are inline anyway */
1685 +static inline int fetch_and_inc(int *val)
1686 +{
1687 +	return atomic_add_return(1, (atomic_t*) val) - 1;
1688 +}
1689 +
1690 +static inline int fetch_and_dec(int *val)
1691 +{
1692 +	return atomic_sub_return(1, (atomic_t*) val) + 1;
1693 +}
1694 +
1695 +/* Don't use rewriting implementation if kernel text pages are read-only.
1696 + * Ftrace gets around this by using the identity mapping, but that's more
1697 + * effort that is warrented right now for Feather-Trace.
1698 + * Eventually, it may make sense to replace Feather-Trace with ftrace.
1699 + */
1700 +#if defined(CONFIG_ARCH_HAS_FEATHER_TRACE) && !defined(CONFIG_DEBUG_RODATA)
1701 +
1702 +#include <asm/feather_trace.h>
1703 +
1704 +#else /* !__ARCH_HAS_FEATHER_TRACE */
1705 +
1706 +/* provide default implementation */
1707 +
1708 +#include <asm/timex.h> /* for get_cycles() */
1709 +
1710 +static inline unsigned long long ft_timestamp(void)
1711 +{
1712 +	return get_cycles();
1713 +}
1714 +
1715 +#define feather_callback
1716 +
1717 +#define MAX_EVENTS 1024
1718 +
1719 +extern int ft_events[MAX_EVENTS];
1720 +
1721 +#define ft_event(id, callback) \
1722 +	if (ft_events[id]) callback();
1723 +
1724 +#define ft_event0(id, callback) \
1725 +	if (ft_events[id]) callback(id);
1726 +
1727 +#define ft_event1(id, callback, param) \
1728 +	if (ft_events[id]) callback(id, param);
1729 +
1730 +#define ft_event2(id, callback, param, param2) \
1731 +	if (ft_events[id]) callback(id, param, param2);
1732 +
1733 +#define ft_event3(id, callback, p, p2, p3) \
1734 +	if (ft_events[id]) callback(id, p, p2, p3);
1735 +
1736 +#endif /* __ARCH_HAS_FEATHER_TRACE */
1737 +
1738 +#endif
1739 diff --git a/include/litmus/ftdev.h b/include/litmus/ftdev.h
1740 new file mode 100644
1741 index 0000000..0b95987
1742 --- /dev/null
1743 +++ b/include/litmus/ftdev.h
1744 @@ -0,0 +1,55 @@
1745 +#ifndef _LITMUS_FTDEV_H_
1746 +#define	_LITMUS_FTDEV_H_
1747 +
1748 +#include <litmus/feather_trace.h>
1749 +#include <litmus/feather_buffer.h>
1750 +#include <linux/mutex.h>
1751 +#include <linux/cdev.h>
1752 +
1753 +#define FTDEV_ENABLE_CMD 	0
1754 +#define FTDEV_DISABLE_CMD 	1
1755 +
1756 +struct ftdev;
1757 +
1758 +/* return 0 if buffer can be opened, otherwise -$REASON */
1759 +typedef int  (*ftdev_can_open_t)(struct ftdev* dev, unsigned int buf_no);
1760 +/* return 0 on success, otherwise -$REASON */
1761 +typedef int  (*ftdev_alloc_t)(struct ftdev* dev, unsigned int buf_no);
1762 +typedef void (*ftdev_free_t)(struct ftdev* dev, unsigned int buf_no);
1763 +/* Let devices handle writes from userspace. No synchronization provided. */
1764 +typedef ssize_t (*ftdev_write_t)(struct ft_buffer* buf, size_t len, const char __user *from);
1765 +
1766 +struct ftdev_event;
1767 +
1768 +struct ftdev_minor {
1769 +	struct ft_buffer*	buf;
1770 +	unsigned int		readers;
1771 +	struct mutex		lock;
1772 +	/* FIXME: filter for authorized events */
1773 +	struct ftdev_event*	events;
1774 +	struct device*		device;
1775 +	struct ftdev*		ftdev;
1776 +};
1777 +
1778 +struct ftdev {
1779 +	dev_t			major;
1780 +	struct cdev		cdev;
1781 +	struct class*		class;
1782 +	const char*		name;
1783 +	struct ftdev_minor*	minor;
1784 +	unsigned int		minor_cnt;
1785 +	ftdev_alloc_t		alloc;
1786 +	ftdev_free_t		free;
1787 +	ftdev_can_open_t	can_open;
1788 +	ftdev_write_t		write;
1789 +};
1790 +
1791 +struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size);
1792 +void free_ft_buffer(struct ft_buffer* buf);
1793 +
1794 +int ftdev_init(	struct ftdev* ftdev, struct module* owner,
1795 +		const int minor_cnt, const char* name);
1796 +void ftdev_exit(struct ftdev* ftdev);
1797 +int register_ftdev(struct ftdev* ftdev);
1798 +
1799 +#endif
1800 diff --git a/include/litmus/jobs.h b/include/litmus/jobs.h
1801 new file mode 100644
1802 index 0000000..9bd361e
1803 --- /dev/null
1804 +++ b/include/litmus/jobs.h
1805 @@ -0,0 +1,9 @@
1806 +#ifndef __LITMUS_JOBS_H__
1807 +#define __LITMUS_JOBS_H__
1808 +
1809 +void prepare_for_next_period(struct task_struct *t);
1810 +void release_at(struct task_struct *t, lt_t start);
1811 +long complete_job(void);
1812 +
1813 +#endif
1814 +
1815 diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
1816 new file mode 100644
1817 index 0000000..12af222
1818 --- /dev/null
1819 +++ b/include/litmus/litmus.h
1820 @@ -0,0 +1,275 @@
1821 +/*
1822 + * Constant definitions related to
1823 + * scheduling policy.
1824 + */
1825 +
1826 +#ifndef _LINUX_LITMUS_H_
1827 +#define _LINUX_LITMUS_H_
1828 +
1829 +#include <litmus/debug_trace.h>
1830 +
1831 +#ifdef CONFIG_RELEASE_MASTER
1832 +extern atomic_t release_master_cpu;
1833 +#endif
1834 +
1835 +/* in_list - is a given list_head queued on some list?
1836 + */
1837 +static inline int in_list(struct list_head* list)
1838 +{
1839 +	return !(  /* case 1: deleted */
1840 +		   (list->next == LIST_POISON1 &&
1841 +		    list->prev == LIST_POISON2)
1842 +		 ||
1843 +		   /* case 2: initialized */
1844 +		   (list->next == list &&
1845 +		    list->prev == list)
1846 +		);
1847 +}
1848 +
1849 +struct task_struct* __waitqueue_remove_first(wait_queue_head_t *wq);
1850 +
1851 +#define NO_CPU			0xffffffff
1852 +
1853 +void litmus_fork(struct task_struct *tsk);
1854 +void litmus_exec(void);
1855 +/* clean up real-time state of a task */
1856 +void exit_litmus(struct task_struct *dead_tsk);
1857 +
1858 +long litmus_admit_task(struct task_struct *tsk);
1859 +void litmus_exit_task(struct task_struct *tsk);
1860 +
1861 +#define is_realtime(t) 		((t)->policy == SCHED_LITMUS)
1862 +#define rt_transition_pending(t) \
1863 +	((t)->rt_param.transition_pending)
1864 +
1865 +#define tsk_rt(t)		(&(t)->rt_param)
1866 +
1867 +/*	Realtime utility macros */
1868 +#define get_rt_flags(t)		(tsk_rt(t)->flags)
1869 +#define set_rt_flags(t,f) 	(tsk_rt(t)->flags=(f))
1870 +#define get_exec_cost(t)  	(tsk_rt(t)->task_params.exec_cost)
1871 +#define get_exec_time(t)	(tsk_rt(t)->job_params.exec_time)
1872 +#define get_rt_period(t)	(tsk_rt(t)->task_params.period)
1873 +#define get_rt_phase(t)		(tsk_rt(t)->task_params.phase)
1874 +#define get_partition(t) 	(tsk_rt(t)->task_params.cpu)
1875 +#define get_deadline(t)		(tsk_rt(t)->job_params.deadline)
1876 +#define get_release(t)		(tsk_rt(t)->job_params.release)
1877 +#define get_class(t)		(tsk_rt(t)->task_params.cls)
1878 +
1879 +#define is_priority_boosted(t)	(tsk_rt(t)->priority_boosted)
1880 +#define get_boost_start(t)	(tsk_rt(t)->boost_start_time)
1881 +
1882 +inline static int budget_exhausted(struct task_struct* t)
1883 +{
1884 +	return get_exec_time(t) >= get_exec_cost(t);
1885 +}
1886 +
1887 +inline static lt_t budget_remaining(struct task_struct* t)
1888 +{
1889 +	if (!budget_exhausted(t))
1890 +		return get_exec_cost(t) - get_exec_time(t);
1891 +	else
1892 +		/* avoid overflow */
1893 +		return 0;
1894 +}
1895 +
1896 +#define budget_enforced(t) (tsk_rt(t)->task_params.budget_policy != NO_ENFORCEMENT)
1897 +
1898 +#define budget_precisely_enforced(t) (tsk_rt(t)->task_params.budget_policy \
1899 +				      == PRECISE_ENFORCEMENT)
1900 +
1901 +#define is_hrt(t)     		\
1902 +	(tsk_rt(t)->task_params.cls == RT_CLASS_HARD)
1903 +#define is_srt(t)     		\
1904 +	(tsk_rt(t)->task_params.cls == RT_CLASS_SOFT)
1905 +#define is_be(t)      		\
1906 +	(tsk_rt(t)->task_params.cls == RT_CLASS_BEST_EFFORT)
1907 +
1908 +/* Our notion of time within LITMUS: kernel monotonic time. */
1909 +static inline lt_t litmus_clock(void)
1910 +{
1911 +	return ktime_to_ns(ktime_get());
1912 +}
1913 +
1914 +/* A macro to convert from nanoseconds to ktime_t. */
1915 +#define ns_to_ktime(t)		ktime_add_ns(ktime_set(0, 0), t)
1916 +
1917 +#define get_domain(t) (tsk_rt(t)->domain)
1918 +
1919 +/* Honor the flag in the preempt_count variable that is set
1920 + * when scheduling is in progress.
1921 + */
1922 +#define is_running(t) 			\
1923 +	((t)->state == TASK_RUNNING || 	\
1924 +	 task_thread_info(t)->preempt_count & PREEMPT_ACTIVE)
1925 +
1926 +#define is_blocked(t)       \
1927 +	(!is_running(t))
1928 +#define is_released(t, now)	\
1929 +	(lt_before_eq(get_release(t), now))
1930 +#define is_tardy(t, now)    \
1931 +	(lt_before_eq(tsk_rt(t)->job_params.deadline, now))
1932 +
1933 +/* real-time comparison macros */
1934 +#define earlier_deadline(a, b) (lt_before(\
1935 +	(a)->rt_param.job_params.deadline,\
1936 +	(b)->rt_param.job_params.deadline))
1937 +#define earlier_release(a, b)  (lt_before(\
1938 +	(a)->rt_param.job_params.release,\
1939 +	(b)->rt_param.job_params.release))
1940 +
1941 +void preempt_if_preemptable(struct task_struct* t, int on_cpu);
1942 +
1943 +#ifdef CONFIG_LITMUS_LOCKING
1944 +void srp_ceiling_block(void);
1945 +#else
1946 +#define srp_ceiling_block() /* nothing */
1947 +#endif
1948 +
1949 +#define bheap2task(hn) ((struct task_struct*) hn->value)
1950 +
1951 +#ifdef CONFIG_NP_SECTION
1952 +
1953 +static inline int is_kernel_np(struct task_struct *t)
1954 +{
1955 +	return tsk_rt(t)->kernel_np;
1956 +}
1957 +
1958 +static inline int is_user_np(struct task_struct *t)
1959 +{
1960 +	return tsk_rt(t)->ctrl_page ? tsk_rt(t)->ctrl_page->sched.np.flag : 0;
1961 +}
1962 +
1963 +static inline void request_exit_np(struct task_struct *t)
1964 +{
1965 +	if (is_user_np(t)) {
1966 +		/* Set the flag that tells user space to call
1967 +		 * into the kernel at the end of a critical section. */
1968 +		if (likely(tsk_rt(t)->ctrl_page)) {
1969 +			TRACE_TASK(t, "setting delayed_preemption flag\n");
1970 +			tsk_rt(t)->ctrl_page->sched.np.preempt = 1;
1971 +		}
1972 +	}
1973 +}
1974 +
1975 +static inline void make_np(struct task_struct *t)
1976 +{
1977 +	tsk_rt(t)->kernel_np++;
1978 +}
1979 +
1980 +/* Caller should check if preemption is necessary when
1981 + * the function return 0.
1982 + */
1983 +static inline int take_np(struct task_struct *t)
1984 +{
1985 +	return --tsk_rt(t)->kernel_np;
1986 +}
1987 +
1988 +/* returns 0 if remote CPU needs an IPI to preempt, 1 if no IPI is required */
1989 +static inline int request_exit_np_atomic(struct task_struct *t)
1990 +{
1991 +	union np_flag old, new;
1992 +
1993 +	if (tsk_rt(t)->ctrl_page) {
1994 +		old.raw = tsk_rt(t)->ctrl_page->sched.raw;
1995 +		if (old.np.flag == 0) {
1996 +			/* no longer non-preemptive */
1997 +			return 0;
1998 +		} else if (old.np.preempt) {
1999 +			/* already set, nothing for us to do */
2000 +			return 1;
2001 +		} else {
2002 +			/* non preemptive and flag not set */
2003 +			new.raw = old.raw;
2004 +			new.np.preempt = 1;
2005 +			/* if we get old back, then we atomically set the flag */
2006 +			return cmpxchg(&tsk_rt(t)->ctrl_page->sched.raw, old.raw, new.raw) == old.raw;
2007 +			/* If we raced with a concurrent change, then so be
2008 +			 * it. Deliver it by IPI.  We don't want an unbounded
2009 +			 * retry loop here since tasks might exploit that to
2010 +			 * keep the kernel busy indefinitely. */
2011 +		}
2012 +	} else
2013 +		return 0;
2014 +}
2015 +
2016 +#else
2017 +
2018 +static inline int is_kernel_np(struct task_struct* t)
2019 +{
2020 +	return 0;
2021 +}
2022 +
2023 +static inline int is_user_np(struct task_struct* t)
2024 +{
2025 +	return 0;
2026 +}
2027 +
2028 +static inline void request_exit_np(struct task_struct *t)
2029 +{
2030 +	/* request_exit_np() shouldn't be called if !CONFIG_NP_SECTION */
2031 +	BUG();
2032 +}
2033 +
2034 +static inline int request_exist_np_atomic(struct task_struct *t)
2035 +{
2036 +	return 0;
2037 +}
2038 +
2039 +#endif
2040 +
2041 +static inline void clear_exit_np(struct task_struct *t)
2042 +{
2043 +	if (likely(tsk_rt(t)->ctrl_page))
2044 +		tsk_rt(t)->ctrl_page->sched.np.preempt = 0;
2045 +}
2046 +
2047 +static inline int is_np(struct task_struct *t)
2048 +{
2049 +#ifdef CONFIG_SCHED_DEBUG_TRACE
2050 +	int kernel, user;
2051 +	kernel = is_kernel_np(t);
2052 +	user   = is_user_np(t);
2053 +	if (kernel || user)
2054 +		TRACE_TASK(t, " is non-preemptive: kernel=%d user=%d\n",
2055 +
2056 +			   kernel, user);
2057 +	return kernel || user;
2058 +#else
2059 +	return unlikely(is_kernel_np(t) || is_user_np(t));
2060 +#endif
2061 +}
2062 +
2063 +static inline int is_present(struct task_struct* t)
2064 +{
2065 +	return t && tsk_rt(t)->present;
2066 +}
2067 +
2068 +
2069 +/* make the unit explicit */
2070 +typedef unsigned long quanta_t;
2071 +
2072 +enum round {
2073 +	FLOOR,
2074 +	CEIL
2075 +};
2076 +
2077 +
2078 +/* Tick period is used to convert ns-specified execution
2079 + * costs and periods into tick-based equivalents.
2080 + */
2081 +extern ktime_t tick_period;
2082 +
2083 +static inline quanta_t time2quanta(lt_t time, enum round round)
2084 +{
2085 +	s64  quantum_length = ktime_to_ns(tick_period);
2086 +
2087 +	if (do_div(time, quantum_length) && round == CEIL)
2088 +		time++;
2089 +	return (quanta_t) time;
2090 +}
2091 +
2092 +/* By how much is cpu staggered behind CPU 0? */
2093 +u64 cpu_stagger_offset(int cpu);
2094 +
2095 +#endif
2096 diff --git a/include/litmus/litmus_proc.h b/include/litmus/litmus_proc.h
2097 new file mode 100644
2098 index 0000000..6800e72
2099 --- /dev/null
2100 +++ b/include/litmus/litmus_proc.h
2101 @@ -0,0 +1,25 @@
2102 +#include <litmus/sched_plugin.h>
2103 +#include <linux/proc_fs.h>
2104 +
2105 +int __init init_litmus_proc(void);
2106 +void exit_litmus_proc(void);
2107 +
2108 +/*
2109 + * On success, returns 0 and sets the pointer to the location of the new
2110 + * proc dir entry, otherwise returns an error code and sets pde to NULL.
2111 + */
2112 +long make_plugin_proc_dir(struct sched_plugin* plugin,
2113 +		struct proc_dir_entry** pde);
2114 +
2115 +/*
2116 + * Plugins should deallocate all child proc directory entries before
2117 + * calling this, to avoid memory leaks.
2118 + */
2119 +void remove_plugin_proc_dir(struct sched_plugin* plugin);
2120 +
2121 +
2122 +/* Copy at most size-1 bytes from ubuf into kbuf, null-terminate buf, and
2123 + * remove a '\n' if present. Returns the number of bytes that were read or
2124 + * -EFAULT. */
2125 +int copy_and_chomp(char *kbuf, unsigned long ksize,
2126 +		   __user const char* ubuf, unsigned long ulength);
2127 diff --git a/include/litmus/locking.h b/include/litmus/locking.h
2128 new file mode 100644
2129 index 0000000..4d7b870
2130 --- /dev/null
2131 +++ b/include/litmus/locking.h
2132 @@ -0,0 +1,28 @@
2133 +#ifndef LITMUS_LOCKING_H
2134 +#define LITMUS_LOCKING_H
2135 +
2136 +struct litmus_lock_ops;
2137 +
2138 +/* Generic base struct for LITMUS^RT userspace semaphores.
2139 + * This structure should be embedded in protocol-specific semaphores.
2140 + */
2141 +struct litmus_lock {
2142 +	struct litmus_lock_ops *ops;
2143 +	int type;
2144 +};
2145 +
2146 +struct litmus_lock_ops {
2147 +	/* Current task tries to obtain / drop a reference to a lock.
2148 +	 * Optional methods, allowed by default. */
2149 +	int (*open)(struct litmus_lock*, void* __user);
2150 +	int (*close)(struct litmus_lock*);
2151 +
2152 +	/* Current tries to lock/unlock this lock (mandatory methods). */
2153 +	int (*lock)(struct litmus_lock*);
2154 +	int (*unlock)(struct litmus_lock*);
2155 +
2156 +	/* The lock is no longer being referenced (mandatory method). */
2157 +	void (*deallocate)(struct litmus_lock*);
2158 +};
2159 +
2160 +#endif
2161 diff --git a/include/litmus/preempt.h b/include/litmus/preempt.h
2162 new file mode 100644
2163 index 0000000..380b886
2164 --- /dev/null
2165 +++ b/include/litmus/preempt.h
2166 @@ -0,0 +1,164 @@
2167 +#ifndef LITMUS_PREEMPT_H
2168 +#define LITMUS_PREEMPT_H
2169 +
2170 +#include <linux/types.h>
2171 +#include <linux/cache.h>
2172 +#include <linux/percpu.h>
2173 +#include <asm/atomic.h>
2174 +
2175 +#include <litmus/debug_trace.h>
2176 +
2177 +extern DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, resched_state);
2178 +
2179 +#ifdef CONFIG_PREEMPT_STATE_TRACE
2180 +const char* sched_state_name(int s);
2181 +#define TRACE_STATE(fmt, args...) TRACE("SCHED_STATE " fmt, args)
2182 +#else
2183 +#define TRACE_STATE(fmt, args...) /* ignore */
2184 +#endif
2185 +
2186 +#define VERIFY_SCHED_STATE(x)						\
2187 +	do { int __s = get_sched_state();				\
2188 +		if ((__s & (x)) == 0)					\
2189 +			TRACE_STATE("INVALID s=0x%x (%s) not "		\
2190 +				    "in 0x%x (%s) [%s]\n",		\
2191 +				    __s, sched_state_name(__s),		\
2192 +				    (x), #x, __FUNCTION__);		\
2193 +	} while (0);
2194 +
2195 +#define TRACE_SCHED_STATE_CHANGE(x, y, cpu)				\
2196 +	TRACE_STATE("[P%d] 0x%x (%s) -> 0x%x (%s)\n",			\
2197 +		    cpu,  (x), sched_state_name(x),			\
2198 +		    (y), sched_state_name(y))
2199 +
2200 +
2201 +typedef enum scheduling_state {
2202 +	TASK_SCHEDULED    = (1 << 0),  /* The currently scheduled task is the one that
2203 +					* should be scheduled, and the processor does not
2204 +					* plan to invoke schedule(). */
2205 +	SHOULD_SCHEDULE   = (1 << 1),  /* A remote processor has determined that the
2206 +					* processor should reschedule, but this has not
2207 +					* been communicated yet (IPI still pending). */
2208 +	WILL_SCHEDULE     = (1 << 2),  /* The processor has noticed that it has to
2209 +					* reschedule and will do so shortly. */
2210 +	TASK_PICKED       = (1 << 3),  /* The processor is currently executing schedule(),
2211 +					* has selected a new task to schedule, but has not
2212 +					* yet performed the actual context switch. */
2213 +	PICKED_WRONG_TASK = (1 << 4),  /* The processor has not yet performed the context
2214 +					* switch, but a remote processor has already
2215 +					* determined that a higher-priority task became
2216 +					* eligible after the task was picked. */
2217 +} sched_state_t;
2218 +
2219 +static inline sched_state_t get_sched_state_on(int cpu)
2220 +{
2221 +	return atomic_read(&per_cpu(resched_state, cpu));
2222 +}
2223 +
2224 +static inline sched_state_t get_sched_state(void)
2225 +{
2226 +	return atomic_read(&__get_cpu_var(resched_state));
2227 +}
2228 +
2229 +static inline int is_in_sched_state(int possible_states)
2230 +{
2231 +	return get_sched_state() & possible_states;
2232 +}
2233 +
2234 +static inline int cpu_is_in_sched_state(int cpu, int possible_states)
2235 +{
2236 +	return get_sched_state_on(cpu) & possible_states;
2237 +}
2238 +
2239 +static inline void set_sched_state(sched_state_t s)
2240 +{
2241 +	TRACE_SCHED_STATE_CHANGE(get_sched_state(), s, smp_processor_id());
2242 +	atomic_set(&__get_cpu_var(resched_state), s);
2243 +}
2244 +
2245 +static inline int sched_state_transition(sched_state_t from, sched_state_t to)
2246 +{
2247 +	sched_state_t old_state;
2248 +
2249 +	old_state = atomic_cmpxchg(&__get_cpu_var(resched_state), from, to);
2250 +	if (old_state == from) {
2251 +		TRACE_SCHED_STATE_CHANGE(from, to, smp_processor_id());
2252 +		return 1;
2253 +	} else
2254 +		return 0;
2255 +}
2256 +
2257 +static inline int sched_state_transition_on(int cpu,
2258 +					    sched_state_t from,
2259 +					    sched_state_t to)
2260 +{
2261 +	sched_state_t old_state;
2262 +
2263 +	old_state = atomic_cmpxchg(&per_cpu(resched_state, cpu), from, to);
2264 +	if (old_state == from) {
2265 +		TRACE_SCHED_STATE_CHANGE(from, to, cpu);
2266 +		return 1;
2267 +	} else
2268 +		return 0;
2269 +}
2270 +
2271 +/* Plugins must call this function after they have decided which job to
2272 + * schedule next.  IMPORTANT: this function must be called while still holding
2273 + * the lock that is used to serialize scheduling decisions.
2274 + *
2275 + * (Ideally, we would like to use runqueue locks for this purpose, but that
2276 + * would lead to deadlocks with the migration code.)
2277 + */
2278 +static inline void sched_state_task_picked(void)
2279 +{
2280 +	VERIFY_SCHED_STATE(WILL_SCHEDULE);
2281 +
2282 +	/* WILL_SCHEDULE has only a local tansition => simple store is ok */
2283 +	set_sched_state(TASK_PICKED);
2284 +}
2285 +
2286 +static inline void sched_state_entered_schedule(void)
2287 +{
2288 +	/* Update state for the case that we entered schedule() not due to
2289 +	 * set_tsk_need_resched() */
2290 +	set_sched_state(WILL_SCHEDULE);
2291 +}
2292 +
2293 +/* Called by schedule() to check if the scheduling decision is still valid
2294 + * after a context switch. Returns 1 if the CPU needs to reschdule. */
2295 +static inline int sched_state_validate_switch(void)
2296 +{
2297 +	int left_state_ok = 0;
2298 +
2299 +	VERIFY_SCHED_STATE(PICKED_WRONG_TASK | TASK_PICKED);
2300 +
2301 +	if (is_in_sched_state(TASK_PICKED)) {
2302 +		/* Might be good; let's try to transition out of this
2303 +		 * state. This must be done atomically since remote processors
2304 +		 * may try to change the state, too. */
2305 +		left_state_ok = sched_state_transition(TASK_PICKED, TASK_SCHEDULED);
2306 +	}
2307 +
2308 +	if (!left_state_ok) {
2309 +		/* We raced with a higher-priority task arrival => not
2310 +		 * valid. The CPU needs to reschedule. */
2311 +		set_sched_state(WILL_SCHEDULE);
2312 +		return 1;
2313 +	} else
2314 +		return 0;
2315 +}
2316 +
2317 +/* State transition events. See litmus/preempt.c for details. */
2318 +void sched_state_will_schedule(struct task_struct* tsk);
2319 +void sched_state_ipi(void);
2320 +/* Cause a CPU (remote or local) to reschedule. */
2321 +void litmus_reschedule(int cpu);
2322 +void litmus_reschedule_local(void);
2323 +
2324 +#ifdef CONFIG_DEBUG_KERNEL
2325 +void sched_state_plugin_check(void);
2326 +#else
2327 +#define sched_state_plugin_check() /* no check */
2328 +#endif
2329 +
2330 +#endif
2331 diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h
2332 new file mode 100644
2333 index 0000000..ac24929
2334 --- /dev/null
2335 +++ b/include/litmus/rt_domain.h
2336 @@ -0,0 +1,182 @@
2337 +/* CLEANUP: Add comments and make it less messy.
2338 + *
2339 + */
2340 +
2341 +#ifndef __UNC_RT_DOMAIN_H__
2342 +#define __UNC_RT_DOMAIN_H__
2343 +
2344 +#include <litmus/bheap.h>
2345 +
2346 +#define RELEASE_QUEUE_SLOTS 127 /* prime */
2347 +
2348 +struct _rt_domain;
2349 +
2350 +typedef int (*check_resched_needed_t)(struct _rt_domain *rt);
2351 +typedef void (*release_jobs_t)(struct _rt_domain *rt, struct bheap* tasks);
2352 +
2353 +struct release_queue {
2354 +	/* each slot maintains a list of release heaps sorted
2355 +	 * by release time */
2356 +	struct list_head		slot[RELEASE_QUEUE_SLOTS];
2357 +};
2358 +
2359 +typedef struct _rt_domain {
2360 +	/* runnable rt tasks are in here */
2361 +	raw_spinlock_t 			ready_lock;
2362 +	struct bheap	 		ready_queue;
2363 +
2364 +	/* real-time tasks waiting for release are in here */
2365 +	raw_spinlock_t 			release_lock;
2366 +	struct release_queue 		release_queue;
2367 +
2368 +#ifdef CONFIG_RELEASE_MASTER
2369 +	int				release_master;
2370 +#endif
2371 +
2372 +	/* for moving tasks to the release queue */
2373 +	raw_spinlock_t			tobe_lock;
2374 +	struct list_head		tobe_released;
2375 +
2376 +	/* how do we check if we need to kick another CPU? */
2377 +	check_resched_needed_t		check_resched;
2378 +
2379 +	/* how do we release jobs? */
2380 +	release_jobs_t			release_jobs;
2381 +
2382 +	/* how are tasks ordered in the ready queue? */
2383 +	bheap_prio_t			order;
2384 +} rt_domain_t;
2385 +
2386 +struct release_heap {
2387 +	/* list_head for per-time-slot list */
2388 +	struct list_head		list;
2389 +	lt_t				release_time;
2390 +	/* all tasks to be released at release_time */
2391 +	struct bheap			heap;
2392 +	/* used to trigger the release */
2393 +	struct hrtimer			timer;
2394 +
2395 +#ifdef CONFIG_RELEASE_MASTER
2396 +	/* used to delegate releases */
2397 +	struct hrtimer_start_on_info	info;
2398 +#endif
2399 +	/* required for the timer callback */
2400 +	rt_domain_t*			dom;
2401 +};
2402 +
2403 +
2404 +static inline struct task_struct* __next_ready(rt_domain_t* rt)
2405 +{
2406 +	struct bheap_node *hn = bheap_peek(rt->order, &rt->ready_queue);
2407 +	if (hn)
2408 +		return bheap2task(hn);
2409 +	else
2410 +		return NULL;
2411 +}
2412 +
2413 +void rt_domain_init(rt_domain_t *rt, bheap_prio_t order,
2414 +		    check_resched_needed_t check,
2415 +		    release_jobs_t relase);
2416 +
2417 +void __add_ready(rt_domain_t* rt, struct task_struct *new);
2418 +void __merge_ready(rt_domain_t* rt, struct bheap *tasks);
2419 +void __add_release(rt_domain_t* rt, struct task_struct *task);
2420 +
2421 +static inline struct task_struct* __take_ready(rt_domain_t* rt)
2422 +{
2423 +	struct bheap_node* hn = bheap_take(rt->order, &rt->ready_queue);
2424 +	if (hn)
2425 +		return bheap2task(hn);
2426 +	else
2427 +		return NULL;
2428 +}
2429 +
2430 +static inline struct task_struct* __peek_ready(rt_domain_t* rt)
2431 +{
2432 +	struct bheap_node* hn = bheap_peek(rt->order, &rt->ready_queue);
2433 +	if (hn)
2434 +		return bheap2task(hn);
2435 +	else
2436 +		return NULL;
2437 +}
2438 +
2439 +static inline int  is_queued(struct task_struct *t)
2440 +{
2441 +	BUG_ON(!tsk_rt(t)->heap_node);
2442 +	return bheap_node_in_heap(tsk_rt(t)->heap_node);
2443 +}
2444 +
2445 +static inline void remove(rt_domain_t* rt, struct task_struct *t)
2446 +{
2447 +	bheap_delete(rt->order, &rt->ready_queue, tsk_rt(t)->heap_node);
2448 +}
2449 +
2450 +static inline void add_ready(rt_domain_t* rt, struct task_struct *new)
2451 +{
2452 +	unsigned long flags;
2453 +	/* first we need the write lock for rt_ready_queue */
2454 +	raw_spin_lock_irqsave(&rt->ready_lock, flags);
2455 +	__add_ready(rt, new);
2456 +	raw_spin_unlock_irqrestore(&rt->ready_lock, flags);
2457 +}
2458 +
2459 +static inline void merge_ready(rt_domain_t* rt, struct bheap* tasks)
2460 +{
2461 +	unsigned long flags;
2462 +	raw_spin_lock_irqsave(&rt->ready_lock, flags);
2463 +	__merge_ready(rt, tasks);
2464 +	raw_spin_unlock_irqrestore(&rt->ready_lock, flags);
2465 +}
2466 +
2467 +static inline struct task_struct* take_ready(rt_domain_t* rt)
2468 +{
2469 +	unsigned long flags;
2470 +	struct task_struct* ret;
2471 +	/* first we need the write lock for rt_ready_queue */
2472 +	raw_spin_lock_irqsave(&rt->ready_lock, flags);
2473 +	ret = __take_ready(rt);
2474 +	raw_spin_unlock_irqrestore(&rt->ready_lock, flags);
2475 +	return ret;
2476 +}
2477 +
2478 +
2479 +static inline void add_release(rt_domain_t* rt, struct task_struct *task)
2480 +{
2481 +	unsigned long flags;
2482 +	raw_spin_lock_irqsave(&rt->tobe_lock, flags);
2483 +	__add_release(rt, task);
2484 +	raw_spin_unlock_irqrestore(&rt->tobe_lock, flags);
2485 +}
2486 +
2487 +#ifdef CONFIG_RELEASE_MASTER
2488 +void __add_release_on(rt_domain_t* rt, struct task_struct *task,
2489 +		      int target_cpu);
2490 +
2491 +static inline void add_release_on(rt_domain_t* rt,
2492 +				  struct task_struct *task,
2493 +				  int target_cpu)
2494 +{
2495 +	unsigned long flags;
2496 +	raw_spin_lock_irqsave(&rt->tobe_lock, flags);
2497 +	__add_release_on(rt, task, target_cpu);
2498 +	raw_spin_unlock_irqrestore(&rt->tobe_lock, flags);
2499 +}
2500 +#endif
2501 +
2502 +static inline int __jobs_pending(rt_domain_t* rt)
2503 +{
2504 +	return !bheap_empty(&rt->ready_queue);
2505 +}
2506 +
2507 +static inline int jobs_pending(rt_domain_t* rt)
2508 +{
2509 +	unsigned long flags;
2510 +	int ret;
2511 +	/* first we need the write lock for rt_ready_queue */
2512 +	raw_spin_lock_irqsave(&rt->ready_lock, flags);
2513 +	ret = !bheap_empty(&rt->ready_queue);
2514 +	raw_spin_unlock_irqrestore(&rt->ready_lock, flags);
2515 +	return ret;
2516 +}
2517 +
2518 +#endif
2519 diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
2520 new file mode 100644
2521 index 0000000..d6d7991
2522 --- /dev/null
2523 +++ b/include/litmus/rt_param.h
2524 @@ -0,0 +1,209 @@
2525 +/*
2526 + * Definition of the scheduler plugin interface.
2527 + *
2528 + */
2529 +#ifndef _LINUX_RT_PARAM_H_
2530 +#define _LINUX_RT_PARAM_H_
2531 +
2532 +/* Litmus time type. */
2533 +typedef unsigned long long lt_t;
2534 +
2535 +static inline int lt_after(lt_t a, lt_t b)
2536 +{
2537 +	return ((long long) b) - ((long long) a) < 0;
2538 +}
2539 +#define lt_before(a, b) lt_after(b, a)
2540 +
2541 +static inline int lt_after_eq(lt_t a, lt_t b)
2542 +{
2543 +	return ((long long) a) - ((long long) b) >= 0;
2544 +}
2545 +#define lt_before_eq(a, b) lt_after_eq(b, a)
2546 +
2547 +/* different types of clients */
2548 +typedef enum {
2549 +	RT_CLASS_HARD,
2550 +	RT_CLASS_SOFT,
2551 +	RT_CLASS_BEST_EFFORT
2552 +} task_class_t;
2553 +
2554 +typedef enum {
2555 +	NO_ENFORCEMENT,      /* job may overrun unhindered */
2556 +	QUANTUM_ENFORCEMENT, /* budgets are only checked on quantum boundaries */
2557 +	PRECISE_ENFORCEMENT  /* budgets are enforced with hrtimers */
2558 +} budget_policy_t;
2559 +
2560 +struct rt_task {
2561 +	lt_t 		exec_cost;
2562 +	lt_t 		period;
2563 +	lt_t		phase;
2564 +	unsigned int	cpu;
2565 +	task_class_t	cls;
2566 +	budget_policy_t budget_policy; /* ignored by pfair */
2567 +};
2568 +
2569 +union np_flag {
2570 +	uint32_t raw;
2571 +	struct {
2572 +		/* Is the task currently in a non-preemptive section? */
2573 +		uint32_t flag:31;
2574 +		/* Should the task call into the scheduler? */
2575 +		uint32_t preempt:1;
2576 +	} np;
2577 +};
2578 +
2579 +/* The definition of the data that is shared between the kernel and real-time
2580 + * tasks via a shared page (see litmus/ctrldev.c).
2581 + *
2582 + * WARNING: User space can write to this, so don't trust
2583 + * the correctness of the fields!
2584 + *
2585 + * This servees two purposes: to enable efficient signaling
2586 + * of non-preemptive sections (user->kernel) and
2587 + * delayed preemptions (kernel->user), and to export
2588 + * some real-time relevant statistics such as preemption and
2589 + * migration data to user space. We can't use a device to export
2590 + * statistics because we want to avoid system call overhead when
2591 + * determining preemption/migration overheads).
2592 + */
2593 +struct control_page {
2594 +	volatile union np_flag sched;
2595 +
2596 +	/* to be extended */
2597 +};
2598 +
2599 +/* don't export internal data structures to user space (liblitmus) */
2600 +#ifdef __KERNEL__
2601 +
2602 +struct _rt_domain;
2603 +struct bheap_node;
2604 +struct release_heap;
2605 +
2606 +struct rt_job {
2607 +	/* Time instant the the job was or will be released.  */
2608 +	lt_t	release;
2609 +	/* What is the current deadline? */
2610 +	lt_t   	deadline;
2611 +
2612 +	/* How much service has this job received so far? */
2613 +	lt_t	exec_time;
2614 +
2615 +	/* Which job is this. This is used to let user space
2616 +	 * specify which job to wait for, which is important if jobs
2617 +	 * overrun. If we just call sys_sleep_next_period() then we
2618 +	 * will unintentionally miss jobs after an overrun.
2619 +	 *
2620 +	 * Increase this sequence number when a job is released.
2621 +	 */
2622 +	unsigned int    job_no;
2623 +};
2624 +
2625 +struct pfair_param;
2626 +
2627 +/*	RT task parameters for scheduling extensions
2628 + *	These parameters are inherited during clone and therefore must
2629 + *	be explicitly set up before the task set is launched.
2630 + */
2631 +struct rt_param {
2632 +	/* is the task sleeping? */
2633 +	unsigned int 		flags:8;
2634 +
2635 +	/* do we need to check for srp blocking? */
2636 +	unsigned int		srp_non_recurse:1;
2637 +
2638 +	/* is the task present? (true if it can be scheduled) */
2639 +	unsigned int		present:1;
2640 +
2641 +#ifdef CONFIG_LITMUS_LOCKING
2642 +	/* Is the task being priority-boosted by a locking protocol? */
2643 +	unsigned int		priority_boosted:1;
2644 +	/* If so, when did this start? */
2645 +	lt_t			boost_start_time;
2646 +#endif
2647 +
2648 +	/* user controlled parameters */
2649 +	struct rt_task 		task_params;
2650 +
2651 +	/* timing parameters */
2652 +	struct rt_job 		job_params;
2653 +
2654 +	/* task representing the current "inherited" task
2655 +	 * priority, assigned by inherit_priority and
2656 +	 * return priority in the scheduler plugins.
2657 +	 * could point to self if PI does not result in
2658 +	 * an increased task priority.
2659 +	 */
2660 +	 struct task_struct*	inh_task;
2661 +
2662 +#ifdef CONFIG_NP_SECTION
2663 +	/* For the FMLP under PSN-EDF, it is required to make the task
2664 +	 * non-preemptive from kernel space. In order not to interfere with
2665 +	 * user space, this counter indicates the kernel space np setting.
2666 +	 * kernel_np > 0 => task is non-preemptive
2667 +	 */
2668 +	unsigned int	kernel_np;
2669 +#endif
2670 +
2671 +	/* This field can be used by plugins to store where the task
2672 +	 * is currently scheduled. It is the responsibility of the
2673 +	 * plugin to avoid race conditions.
2674 +	 *
2675 +	 * This used by GSN-EDF and PFAIR.
2676 +	 */
2677 +	volatile int		scheduled_on;
2678 +
2679 +	/* Is the stack of the task currently in use? This is updated by
2680 +	 * the LITMUS core.
2681 +	 *
2682 +	 * Be careful to avoid deadlocks!
2683 +	 */
2684 +	volatile int		stack_in_use;
2685 +
2686 +	/* This field can be used by plugins to store where the task
2687 +	 * is currently linked. It is the responsibility of the plugin
2688 +	 * to avoid race conditions.
2689 +	 *
2690 +	 * Used by GSN-EDF.
2691 +	 */
2692 +	volatile int		linked_on;
2693 +
2694 +	/* PFAIR/PD^2 state. Allocated on demand. */
2695 +	struct pfair_param*	pfair;
2696 +
2697 +	/* Fields saved before BE->RT transition.
2698 +	 */
2699 +	int old_policy;
2700 +	int old_prio;
2701 +
2702 +	/* ready queue for this task */
2703 +	struct _rt_domain* domain;
2704 +
2705 +	/* heap element for this task
2706 +	 *
2707 +	 * Warning: Don't statically allocate this node. The heap
2708 +	 *          implementation swaps these between tasks, thus after
2709 +	 *          dequeuing from a heap you may end up with a different node
2710 +	 *          then the one you had when enqueuing the task.  For the same
2711 +	 *          reason, don't obtain and store references to this node
2712 +	 *          other than this pointer (which is updated by the heap
2713 +	 *          implementation).
2714 +	 */
2715 +	struct bheap_node*	heap_node;
2716 +	struct release_heap*	rel_heap;
2717 +
2718 +	/* Used by rt_domain to queue task in release list.
2719 +	 */
2720 +	struct list_head list;
2721 +
2722 +	/* Pointer to the page shared between userspace and kernel. */
2723 +	struct control_page * ctrl_page;
2724 +};
2725 +
2726 +/*	Possible RT flags	*/
2727 +#define RT_F_RUNNING		0x00000000
2728 +#define RT_F_SLEEP		0x00000001
2729 +#define RT_F_EXIT_SEM		0x00000008
2730 +
2731 +#endif
2732 +
2733 +#endif
2734 diff --git a/include/litmus/sched_plugin.h b/include/litmus/sched_plugin.h
2735 new file mode 100644
2736 index 0000000..6e7cabd
2737 --- /dev/null
2738 +++ b/include/litmus/sched_plugin.h
2739 @@ -0,0 +1,111 @@
2740 +/*
2741 + * Definition of the scheduler plugin interface.
2742 + *
2743 + */
2744 +#ifndef _LINUX_SCHED_PLUGIN_H_
2745 +#define _LINUX_SCHED_PLUGIN_H_
2746 +
2747 +#include <linux/sched.h>
2748 +
2749 +#ifdef CONFIG_LITMUS_LOCKING
2750 +#include <litmus/locking.h>
2751 +#endif
2752 +
2753 +/************************ setup/tear down ********************/
2754 +
2755 +typedef long (*activate_plugin_t) (void);
2756 +typedef long (*deactivate_plugin_t) (void);
2757 +
2758 +
2759 +
2760 +/********************* scheduler invocation ******************/
2761 +
2762 +/*  Plugin-specific realtime tick handler */
2763 +typedef void (*scheduler_tick_t) (struct task_struct *cur);
2764 +/* Novell make sched decision function */
2765 +typedef struct task_struct* (*schedule_t)(struct task_struct * prev);
2766 +/* Clean up after the task switch has occured.
2767 + * This function is called after every (even non-rt) task switch.
2768 + */
2769 +typedef void (*finish_switch_t)(struct task_struct *prev);
2770 +
2771 +
2772 +/********************* task state changes ********************/
2773 +
2774 +/* Called to setup a new real-time task.
2775 + * Release the first job, enqueue, etc.
2776 + * Task may already be running.
2777 + */
2778 +typedef void (*task_new_t) (struct task_struct *task,
2779 +			    int on_rq,
2780 +			    int running);
2781 +
2782 +/* Called to re-introduce a task after blocking.
2783 + * Can potentially be called multiple times.
2784 + */
2785 +typedef void (*task_wake_up_t) (struct task_struct *task);
2786 +/* called to notify the plugin of a blocking real-time task
2787 + * it will only be called for real-time tasks and before schedule is called */
2788 +typedef void (*task_block_t)  (struct task_struct *task);
2789 +/* Called when a real-time task exits or changes to a different scheduling
2790 + * class.
2791 + * Free any allocated resources
2792 + */
2793 +typedef void (*task_exit_t)    (struct task_struct *);
2794 +
2795 +/* Called when the current task attempts to create a new lock of a given
2796 + * protocol type. */
2797 +typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type,
2798 +				 void* __user config);
2799 +
2800 +
2801 +/********************* sys call backends  ********************/
2802 +/* This function causes the caller to sleep until the next release */
2803 +typedef long (*complete_job_t) (void);
2804 +
2805 +typedef long (*admit_task_t)(struct task_struct* tsk);
2806 +
2807 +typedef void (*release_at_t)(struct task_struct *t, lt_t start);
2808 +
2809 +struct sched_plugin {
2810 +	struct list_head	list;
2811 +	/* 	basic info 		*/
2812 +	char 			*plugin_name;
2813 +
2814 +	/*	setup			*/
2815 +	activate_plugin_t	activate_plugin;
2816 +	deactivate_plugin_t	deactivate_plugin;
2817 +
2818 +	/* 	scheduler invocation 	*/
2819 +	scheduler_tick_t        tick;
2820 +	schedule_t 		schedule;
2821 +	finish_switch_t 	finish_switch;
2822 +
2823 +	/*	syscall backend 	*/
2824 +	complete_job_t 		complete_job;
2825 +	release_at_t		release_at;
2826 +
2827 +	/*	task state changes 	*/
2828 +	admit_task_t		admit_task;
2829 +
2830 +        task_new_t 		task_new;
2831 +	task_wake_up_t		task_wake_up;
2832 +	task_block_t		task_block;
2833 +	task_exit_t 		task_exit;
2834 +
2835 +#ifdef CONFIG_LITMUS_LOCKING
2836 +	/*	locking protocols	*/
2837 +	allocate_lock_t		allocate_lock;
2838 +#endif
2839 +} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
2840 +
2841 +
2842 +extern struct sched_plugin *litmus;
2843 +
2844 +int register_sched_plugin(struct sched_plugin* plugin);
2845 +struct sched_plugin* find_sched_plugin(const char* name);
2846 +int print_sched_plugins(char* buf, int max);
2847 +
2848 +extern struct sched_plugin linux_sched_plugin;
2849 +
2850 +#endif
2851 diff --git a/include/litmus/sched_trace.h b/include/litmus/sched_trace.h
2852 new file mode 100644
2853 index 0000000..7ca34cb
2854 --- /dev/null
2855 +++ b/include/litmus/sched_trace.h
2856 @@ -0,0 +1,200 @@
2857 +/*
2858 + * sched_trace.h -- record scheduler events to a byte stream for offline analysis.
2859 + */
2860 +#ifndef _LINUX_SCHED_TRACE_H_
2861 +#define _LINUX_SCHED_TRACE_H_
2862 +
2863 +/* all times in nanoseconds */
2864 +
2865 +struct st_trace_header {
2866 +	u8	type;		/* Of what type is this record?  */
2867 +	u8	cpu;		/* On which CPU was it recorded? */
2868 +	u16	pid;		/* PID of the task.              */
2869 +	u32	job;		/* The job sequence number.      */
2870 +};
2871 +
2872 +#define ST_NAME_LEN 16
2873 +struct st_name_data {
2874 +	char	cmd[ST_NAME_LEN];/* The name of the executable of this process. */
2875 +};
2876 +
2877 +struct st_param_data {		/* regular params */
2878 +	u32	wcet;
2879 +	u32	period;
2880 +	u32	phase;
2881 +	u8	partition;
2882 +	u8	class;
2883 +	u8	__unused[2];
2884 +};
2885 +
2886 +struct st_release_data {	/* A job is was/is going to be released. */
2887 +	u64	release;	/* What's the release time?              */
2888 +	u64	deadline;	/* By when must it finish?		 */
2889 +};
2890 +
2891 +struct st_assigned_data {	/* A job was asigned to a CPU. 		 */
2892 +	u64	when;
2893 +	u8	target;		/* Where should it execute?	         */
2894 +	u8	__unused[7];
2895 +};
2896 +
2897 +struct st_switch_to_data {	/* A process was switched to on a given CPU.   */
2898 +	u64	when;		/* When did this occur?                        */
2899 +	u32	exec_time;	/* Time the current job has executed.          */
2900 +	u8	__unused[4];
2901 +
2902 +};
2903 +
2904 +struct st_switch_away_data {	/* A process was switched away from on a given CPU. */
2905 +	u64	when;
2906 +	u64	exec_time;
2907 +};
2908 +
2909 +struct st_completion_data {	/* A job completed. */
2910 +	u64	when;
2911 +	u8	forced:1; 	/* Set to 1 if job overran and kernel advanced to the
2912 +				 * next task automatically; set to 0 otherwise.
2913 +				 */
2914 +	u8	__uflags:7;
2915 +	u8	__unused[7];
2916 +};
2917 +
2918 +struct st_block_data {		/* A task blocks. */
2919 +	u64	when;
2920 +	u64	__unused;
2921 +};
2922 +
2923 +struct st_resume_data {		/* A task resumes. */
2924 +	u64	when;
2925 +	u64	__unused;
2926 +};
2927 +
2928 +struct st_action_data {
2929 +	u64	when;
2930 +	u8	action;
2931 +	u8	__unused[7];
2932 +};
2933 +
2934 +struct st_sys_release_data {
2935 +	u64	when;
2936 +	u64	release;
2937 +};
2938 +
2939 +#define DATA(x) struct st_ ## x ## _data x;
2940 +
2941 +typedef enum {
2942 +        ST_NAME = 1,		/* Start at one, so that we can spot
2943 +				 * uninitialized records. */
2944 +	ST_PARAM,
2945 +	ST_RELEASE,
2946 +	ST_ASSIGNED,
2947 +	ST_SWITCH_TO,
2948 +	ST_SWITCH_AWAY,
2949 +	ST_COMPLETION,
2950 +	ST_BLOCK,
2951 +	ST_RESUME,
2952 +	ST_ACTION,
2953 +	ST_SYS_RELEASE
2954 +} st_event_record_type_t;
2955 +
2956 +struct st_event_record {
2957 +	struct st_trace_header hdr;
2958 +	union {
2959 +		u64 raw[2];
2960 +
2961 +		DATA(name);
2962 +		DATA(param);
2963 +		DATA(release);
2964 +		DATA(assigned);
2965 +		DATA(switch_to);
2966 +		DATA(switch_away);
2967 +		DATA(completion);
2968 +		DATA(block);
2969 +		DATA(resume);
2970 +		DATA(action);
2971 +		DATA(sys_release);
2972 +	} data;
2973 +};
2974 +
2975 +#undef DATA
2976 +
2977 +#ifdef __KERNEL__
2978 +
2979 +#include <linux/sched.h>
2980 +#include <litmus/feather_trace.h>
2981 +
2982 +#ifdef CONFIG_SCHED_TASK_TRACE
2983 +
2984 +#define SCHED_TRACE(id, callback, task) \
2985 +	ft_event1(id, callback, task)
2986 +#define SCHED_TRACE2(id, callback, task, xtra) \
2987 +	ft_event2(id, callback, task, xtra)
2988 +
2989 +/* provide prototypes; needed on sparc64 */
2990 +#ifndef NO_TASK_TRACE_DECLS
2991 +feather_callback void do_sched_trace_task_name(unsigned long id,
2992 +					       struct task_struct* task);
2993 +feather_callback void do_sched_trace_task_param(unsigned long id,
2994 +						struct task_struct* task);
2995 +feather_callback void do_sched_trace_task_release(unsigned long id,
2996 +						  struct task_struct* task);
2997 +feather_callback void do_sched_trace_task_switch_to(unsigned long id,
2998 +						    struct task_struct* task);
2999 +feather_callback void do_sched_trace_task_switch_away(unsigned long id,
3000 +						      struct task_struct* task);
3001 +feather_callback void do_sched_trace_task_completion(unsigned long id,
3002 +						     struct task_struct* task,
3003 +						     unsigned long forced);
3004 +feather_callback void do_sched_trace_task_block(unsigned long id,
3005 +						struct task_struct* task);
3006 +feather_callback void do_sched_trace_task_resume(unsigned long id,
3007 +						 struct task_struct* task);
3008 +feather_callback void do_sched_trace_action(unsigned long id,
3009 +					    struct task_struct* task,
3010 +					    unsigned long action);
3011 +feather_callback void do_sched_trace_sys_release(unsigned long id,
3012 +						 lt_t* start);
3013 +
3014 +#endif
3015 +
3016 +#else
3017 +
3018 +#define SCHED_TRACE(id, callback, task)        /* no tracing */
3019 +#define SCHED_TRACE2(id, callback, task, xtra) /* no tracing */
3020 +
3021 +#endif
3022 +
3023 +
3024 +#define SCHED_TRACE_BASE_ID 500
3025 +
3026 +
3027 +#define sched_trace_task_name(t) \
3028 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 1, do_sched_trace_task_name, t)
3029 +#define sched_trace_task_param(t) \
3030 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 2, do_sched_trace_task_param, t)
3031 +#define sched_trace_task_release(t) \
3032 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 3, do_sched_trace_task_release, t)
3033 +#define sched_trace_task_switch_to(t) \
3034 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 4, do_sched_trace_task_switch_to, t)
3035 +#define sched_trace_task_switch_away(t) \
3036 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 5, do_sched_trace_task_switch_away, t)
3037 +#define sched_trace_task_completion(t, forced) \
3038 +	SCHED_TRACE2(SCHED_TRACE_BASE_ID + 6, do_sched_trace_task_completion, t, \
3039 +		     (unsigned long) forced)
3040 +#define sched_trace_task_block(t) \
3041 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 7, do_sched_trace_task_block, t)
3042 +#define sched_trace_task_resume(t) \
3043 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 8, do_sched_trace_task_resume, t)
3044 +#define sched_trace_action(t, action) \
3045 +	SCHED_TRACE2(SCHED_TRACE_BASE_ID + 9, do_sched_trace_action, t, \
3046 +		     (unsigned long) action);
3047 +/* when is a pointer, it does not need an explicit cast to unsigned long */
3048 +#define sched_trace_sys_release(when) \
3049 +	SCHED_TRACE(SCHED_TRACE_BASE_ID + 10, do_sched_trace_sys_release, when)
3050 +
3051 +
3052 +#define sched_trace_quantum_boundary() /* NOT IMPLEMENTED */
3053 +
3054 +#endif /* __KERNEL__ */
3055 +
3056 +#endif
3057 diff --git a/include/litmus/srp.h b/include/litmus/srp.h
3058 new file mode 100644
3059 index 0000000..c9a4552
3060 --- /dev/null
3061 +++ b/include/litmus/srp.h
3062 @@ -0,0 +1,28 @@
3063 +#ifndef LITMUS_SRP_H
3064 +#define LITMUS_SRP_H
3065 +
3066 +struct srp_semaphore;
3067 +
3068 +struct srp_priority {
3069 +	struct list_head	list;
3070 +        unsigned int 		priority;
3071 +	pid_t			pid;
3072 +};
3073 +#define list2prio(l) list_entry(l, struct srp_priority, list)