Attachment 'tracing-and-dflp-rtas13.patch'

Download

   1 diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
   2 index ed4c4f5..7539d84 100644
   3 --- a/arch/x86/kernel/smp.c
   4 +++ b/arch/x86/kernel/smp.c
   5 @@ -25,7 +25,6 @@
   6  
   7  #include <litmus/preempt.h>
   8  #include <litmus/debug_trace.h>
   9 -#include <litmus/trace.h>
  10  
  11  #include <asm/mtrr.h>
  12  #include <asm/tlbflush.h>
  13 @@ -122,7 +121,6 @@ static void native_smp_send_reschedule(int cpu)
  14  		WARN_ON(1);
  15  		return;
  16  	}
  17 -	TS_SEND_RESCHED_START(cpu);
  18  	apic->send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
  19  }
  20  
  21 @@ -214,18 +212,16 @@ static void native_stop_other_cpus(int wait)
  22  void smp_reschedule_interrupt(struct pt_regs *regs)
  23  {
  24  	ack_APIC_irq();
  25 -	/* LITMUS^RT: this IPI might need to trigger the sched state machine. */
  26 -	sched_state_ipi();
  27  	inc_irq_stat(irq_resched_count);
  28 -	/*
  29 -	 * LITMUS^RT: starting from 3.0 schedule_ipi() actually does something.
  30 -	 * This may increase IPI latencies compared with previous versions.
  31 -	 */
  32  	scheduler_ipi();
  33 -	TS_SEND_RESCHED_END;
  34  	/*
  35  	 * KVM uses this interrupt to force a cpu out of guest mode
  36  	 */
  37 +
  38 +	/* LITMUS^RT: this IPI might need to trigger the sched state machine.
  39 +	 * Starting from 3.0 schedule_ipi() actually does something.  This may
  40 +	 * increase IPI latencies compared with previous versions. */
  41 +	sched_state_ipi();
  42  }
  43  
  44  void smp_call_function_interrupt(struct pt_regs *regs)
  45 @@ -251,8 +247,10 @@ extern void hrtimer_pull(void);
  46  void smp_pull_timers_interrupt(struct pt_regs *regs)
  47  {
  48  	ack_APIC_irq();
  49 +	irq_enter();
  50  	TRACE("pull timer interrupt\n");
  51  	hrtimer_pull();
  52 +	irq_exit();
  53  }
  54  
  55  struct smp_ops smp_ops = {
  56 diff --git a/include/linux/completion.h b/include/linux/completion.h
  57 index 9d72727..51494e6 100644
  58 --- a/include/linux/completion.h
  59 +++ b/include/linux/completion.h
  60 @@ -90,7 +90,6 @@ extern bool completion_done(struct completion *x);
  61  
  62  extern void complete(struct completion *);
  63  extern void complete_all(struct completion *);
  64 -extern void complete_n(struct completion *, int n);
  65  
  66  /**
  67   * INIT_COMPLETION - reinitialize a completion structure
  68 diff --git a/include/litmus/fdso.h b/include/litmus/fdso.h
  69 index f2115b8..fd9b30d 100644
  70 --- a/include/litmus/fdso.h
  71 +++ b/include/litmus/fdso.h
  72 @@ -23,10 +23,11 @@ typedef enum  {
  73  	MPCP_SEM	= 2,
  74  	MPCP_VS_SEM	= 3,
  75  	DPCP_SEM	= 4,
  76 -
  77  	PCP_SEM         = 5,
  78  
  79 -	MAX_OBJ_TYPE	= 5
  80 +	DFLP_SEM	= 6,
  81 +
  82 +	MAX_OBJ_TYPE	= 6
  83  } obj_type_t;
  84  
  85  struct inode_obj_id {
  86 diff --git a/include/litmus/fp_common.h b/include/litmus/fp_common.h
  87 index dd1f7bf..19356c0 100644
  88 --- a/include/litmus/fp_common.h
  89 +++ b/include/litmus/fp_common.h
  90 @@ -57,7 +57,7 @@ static inline unsigned int fpq_find(struct fp_prio_queue* q)
  91  
  92  static inline void fp_prio_add(struct fp_prio_queue* q, struct task_struct* t, unsigned int index)
  93  {
  94 -
  95 +	BUG_ON(index >= LITMUS_MAX_PRIORITY);
  96  	BUG_ON(bheap_node_in_heap(tsk_rt(t)->heap_node));
  97  
  98  	fpq_set(q, index);
  99 diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
 100 index 338245a..9dfcac4 100644
 101 --- a/include/litmus/litmus.h
 102 +++ b/include/litmus/litmus.h
 103 @@ -259,4 +259,39 @@ static inline quanta_t time2quanta(lt_t time, enum round round)
 104  /* By how much is cpu staggered behind CPU 0? */
 105  u64 cpu_stagger_offset(int cpu);
 106  
 107 +static inline struct control_page* get_control_page(struct task_struct *t)
 108 +{
 109 +	return tsk_rt(t)->ctrl_page;
 110 +}
 111 +
 112 +static inline int has_control_page(struct task_struct* t)
 113 +{
 114 +	return tsk_rt(t)->ctrl_page != NULL;
 115 +}
 116 +
 117 +
 118 +#ifdef CONFIG_SCHED_OVERHEAD_TRACE
 119 +
 120 +#define TS_SYSCALL_IN_START						\
 121 +	if (has_control_page(current)) {				\
 122 +		__TS_SYSCALL_IN_START(&get_control_page(current)->ts_syscall_start); \
 123 +	}
 124 +
 125 +#define TS_SYSCALL_IN_END						\
 126 +	if (has_control_page(current)) {				\
 127 +		uint64_t irqs;						\
 128 +		local_irq_disable();					\
 129 +		irqs = get_control_page(current)->irq_count -		\
 130 +			get_control_page(current)->irq_syscall_start;	\
 131 +		__TS_SYSCALL_IN_END(&irqs);				\
 132 +		local_irq_enable();					\
 133 +	}
 134 +
 135 +#else
 136 +
 137 +#define TS_SYSCALL_IN_START
 138 +#define TS_SYSCALL_IN_END
 139 +
 140 +#endif
 141 +
 142  #endif
 143 diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
 144 index 89ac0dd..b77dde9 100644
 145 --- a/include/litmus/rt_param.h
 146 +++ b/include/litmus/rt_param.h
 147 @@ -65,12 +65,12 @@ struct rt_task {
 148  };
 149  
 150  union np_flag {
 151 -	uint32_t raw;
 152 +	uint64_t raw;
 153  	struct {
 154  		/* Is the task currently in a non-preemptive section? */
 155 -		uint32_t flag:31;
 156 +		uint64_t flag:31;
 157  		/* Should the task call into the scheduler? */
 158 -		uint32_t preempt:1;
 159 +		uint64_t preempt:1;
 160  	} np;
 161  };
 162  
 163 @@ -89,11 +89,29 @@ union np_flag {
 164   * determining preemption/migration overheads).
 165   */
 166  struct control_page {
 167 +	/* This flag is used by userspace to communicate non-preempive
 168 +	 * sections. */
 169  	volatile union np_flag sched;
 170  
 171 +	volatile uint64_t irq_count; /* Incremented by the kernel each time an IRQ is
 172 +				      * handled. */
 173 +
 174 +	/* Locking overhead tracing: userspace records here the time stamp
 175 +	 * and IRQ counter prior to starting the system call. */
 176 +	uint64_t ts_syscall_start;  /* Feather-Trace cycles */
 177 +	uint64_t irq_syscall_start; /* Snapshot of irq_count when the syscall
 178 +				     * started. */
 179 +
 180  	/* to be extended */
 181  };
 182  
 183 +/* Expected offsets within the control page. */
 184 +
 185 +#define LITMUS_CP_OFFSET_SCHED		0
 186 +#define LITMUS_CP_OFFSET_IRQ_COUNT	8
 187 +#define LITMUS_CP_OFFSET_TS_SC_START	16
 188 +#define LITMUS_CP_OFFSET_IRQ_SC_START	24
 189 +
 190  /* don't export internal data structures to user space (liblitmus) */
 191  #ifdef __KERNEL__
 192  
 193 diff --git a/include/litmus/trace.h b/include/litmus/trace.h
 194 index e809376..2cd1903 100644
 195 --- a/include/litmus/trace.h
 196 +++ b/include/litmus/trace.h
 197 @@ -16,7 +16,8 @@ enum task_type_marker {
 198  };
 199  
 200  struct timestamp {
 201 -	uint64_t		timestamp;
 202 +	uint64_t		timestamp:48;
 203 +	uint64_t		pid:16;
 204  	uint32_t		seq_no;
 205  	uint8_t			cpu;
 206  	uint8_t			event;
 207 @@ -31,11 +32,16 @@ feather_callback void save_timestamp_def(unsigned long event, unsigned long type
 208  feather_callback void save_timestamp_task(unsigned long event, unsigned long t_ptr);
 209  feather_callback void save_timestamp_cpu(unsigned long event, unsigned long cpu);
 210  feather_callback void save_task_latency(unsigned long event, unsigned long when_ptr);
 211 +feather_callback void save_timestamp_time(unsigned long event, unsigned long time_ptr);
 212 +feather_callback void save_timestamp_irq(unsigned long event, unsigned long irq_count_ptr);
 213 +feather_callback void save_timestamp_hide_irq(unsigned long event);
 214  
 215  #define TIMESTAMP(id) ft_event0(id, save_timestamp)
 216  
 217  #define DTIMESTAMP(id, def)  ft_event1(id, save_timestamp_def, (unsigned long) def)
 218  
 219 +#define TIMESTAMP_CUR(id) DTIMESTAMP(id, is_realtime(current) ? TSK_RT : TSK_BE)
 220 +
 221  #define TTIMESTAMP(id, task) \
 222  	ft_event1(id, save_timestamp_task, (unsigned long) task)
 223  
 224 @@ -45,18 +51,35 @@ feather_callback void save_task_latency(unsigned long event, unsigned long when_
 225  #define LTIMESTAMP(id, task) \
 226  	ft_event1(id, save_task_latency, (unsigned long) task)
 227  
 228 +#define TIMESTAMP_TIME(id, time_ptr) \
 229 +	ft_event1(id, save_timestamp_time, (unsigned long) time_ptr)
 230 +
 231 +#define TIMESTAMP_IRQ(id, irq_count_ptr) \
 232 +	ft_event1(id, save_timestamp_irq, (unsigned long) irq_count_ptr)
 233 +
 234 +#define TIMESTAMP_IN_IRQ(id) \
 235 +	ft_event0(id, save_timestamp_hide_irq)
 236 +
 237  #else /* !CONFIG_SCHED_OVERHEAD_TRACE */
 238  
 239  #define TIMESTAMP(id)        /* no tracing */
 240  
 241  #define DTIMESTAMP(id, def)  /* no tracing */
 242  
 243 +#define TIMESTAMP_CUR(id)    /* no tracing */
 244 +
 245  #define TTIMESTAMP(id, task) /* no tracing */
 246  
 247  #define CTIMESTAMP(id, cpu)  /* no tracing */
 248  
 249  #define LTIMESTAMP(id, when_ptr) /* no tracing */
 250  
 251 +#define TIMESTAMP_TIME(id, time_ptr) /* no tracing */
 252 +
 253 +#define TIMESTAMP_IRQ(id, irq_count_ptr) /* no tracing */
 254 +
 255 +#define TIMESTAMP_IN_IRQ(id) /* no tracing */
 256 +
 257  #endif
 258  
 259  
 260 @@ -68,7 +91,20 @@ feather_callback void save_task_latency(unsigned long event, unsigned long when_
 261   * always the next number after the start time event id.
 262   */
 263  
 264 +#define __TS_SYSCALL_IN_START(p)	TIMESTAMP_TIME(10, p)
 265 +#define __TS_SYSCALL_IN_END(p)		TIMESTAMP_IRQ(11, p)
 266 +
 267 +#define TS_SYSCALL_OUT_START		TIMESTAMP_CUR(20)
 268 +#define TS_SYSCALL_OUT_END		TIMESTAMP_CUR(21)
 269 +
 270 +#define TS_LOCK_START			TIMESTAMP_CUR(30)
 271 +#define TS_LOCK_END			TIMESTAMP_CUR(31)
 272  
 273 +#define TS_LOCK_SUSPEND			TIMESTAMP_CUR(38)
 274 +#define TS_LOCK_RESUME			TIMESTAMP_CUR(39)
 275 +
 276 +#define TS_UNLOCK_START			TIMESTAMP_CUR(40)
 277 +#define TS_UNLOCK_END			TIMESTAMP_CUR(41)
 278  
 279  #define TS_SCHED_START			DTIMESTAMP(100, TSK_UNKNOWN) /* we only
 280  								      * care
 281 @@ -100,16 +136,8 @@ feather_callback void save_task_latency(unsigned long event, unsigned long when_
 282  #define TS_EXIT_NP_START		TIMESTAMP(150)
 283  #define TS_EXIT_NP_END			TIMESTAMP(151)
 284  
 285 -#define TS_LOCK_START			TIMESTAMP(170)
 286 -#define TS_LOCK_SUSPEND			TIMESTAMP(171)
 287 -#define TS_LOCK_RESUME			TIMESTAMP(172)
 288 -#define TS_LOCK_END			TIMESTAMP(173)
 289 -
 290 -#define TS_UNLOCK_START			TIMESTAMP(180)
 291 -#define TS_UNLOCK_END			TIMESTAMP(181)
 292 -
 293  #define TS_SEND_RESCHED_START(c)	CTIMESTAMP(190, c)
 294 -#define TS_SEND_RESCHED_END		DTIMESTAMP(191, TSK_UNKNOWN)
 295 +#define TS_SEND_RESCHED_END		TIMESTAMP_IN_IRQ(191)
 296  
 297  #define TS_RELEASE_LATENCY(when)	LTIMESTAMP(208, &(when))
 298  
 299 diff --git a/include/litmus/trace_irq.h b/include/litmus/trace_irq.h
 300 index f18b127..0d0c042 100644
 301 --- a/include/litmus/trace_irq.h
 302 +++ b/include/litmus/trace_irq.h
 303 @@ -3,14 +3,7 @@
 304  
 305  #ifdef CONFIG_SCHED_OVERHEAD_TRACE
 306  
 307 -extern DEFINE_PER_CPU(atomic_t, irq_fired_count);
 308 -
 309 -static inline void ft_irq_fired(void)
 310 -{
 311 -	/* Only called with preemptions disabled.  */
 312 -	atomic_inc(&__get_cpu_var(irq_fired_count));
 313 -}
 314 -
 315 +void ft_irq_fired(void);
 316  
 317  #else
 318  
 319 diff --git a/kernel/sched.c b/kernel/sched.c
 320 index 2229d0d..71463c8 100644
 321 --- a/kernel/sched.c
 322 +++ b/kernel/sched.c
 323 @@ -2597,8 +2597,12 @@ void scheduler_ipi(void)
 324  	struct rq *rq = this_rq();
 325  	struct task_struct *list = xchg(&rq->wake_list, NULL);
 326  
 327 -	if (!list)
 328 +	if (!list) {
 329 +		/* If we don't call irq_enter(), we need to trigger the IRQ
 330 +		 * tracing manually. */
 331 +		ft_irq_fired();
 332  		return;
 333 +	}
 334  
 335  	/*
 336  	 * Not all reschedule IPI handlers call irq_enter/irq_exit, since
 337 @@ -4403,14 +4407,20 @@ litmus_need_resched_nonpreemptible:
 338  		raw_spin_unlock_irq(&rq->lock);
 339  	}
 340  
 341 +	TS_SCHED2_START(prev);
 342  	sched_trace_task_switch_to(current);
 343  
 344  	post_schedule(rq);
 345  
 346 -	if (sched_state_validate_switch())
 347 +	if (sched_state_validate_switch()) {
 348 +		TS_SCHED2_END(prev);
 349  		goto litmus_need_resched_nonpreemptible;
 350 +	}
 351  
 352  	preempt_enable_no_resched();
 353 +
 354 +	TS_SCHED2_END(prev);
 355 +
 356  	if (need_resched())
 357  		goto need_resched;
 358  
 359 @@ -4684,17 +4694,6 @@ void complete_all(struct completion *x)
 360  }
 361  EXPORT_SYMBOL(complete_all);
 362  
 363 -void complete_n(struct completion *x, int n)
 364 -{
 365 -	unsigned long flags;
 366 -
 367 -	spin_lock_irqsave(&x->wait.lock, flags);
 368 -	x->done += n;
 369 -	__wake_up_common(&x->wait, TASK_NORMAL, n, 0, NULL);
 370 -	spin_unlock_irqrestore(&x->wait.lock, flags);
 371 -}
 372 -EXPORT_SYMBOL(complete_n);
 373 -
 374  static inline long __sched
 375  do_wait_for_common(struct completion *x, long timeout, int state)
 376  {
 377 diff --git a/kernel/softirq.c b/kernel/softirq.c
 378 index fca82c3..2f2df08 100644
 379 --- a/kernel/softirq.c
 380 +++ b/kernel/softirq.c
 381 @@ -211,6 +211,9 @@ asmlinkage void __do_softirq(void)
 382  	int max_restart = MAX_SOFTIRQ_RESTART;
 383  	int cpu;
 384  
 385 +	/* Mark Feather-Trace samples as "disturbed". */
 386 +	ft_irq_fired();
 387 +
 388  	pending = local_softirq_pending();
 389  	account_system_vtime(current);
 390  
 391 diff --git a/litmus/ctrldev.c b/litmus/ctrldev.c
 392 index 9969ab1..41919b2 100644
 393 --- a/litmus/ctrldev.c
 394 +++ b/litmus/ctrldev.c
 395 @@ -133,6 +133,17 @@ static int __init init_litmus_ctrl_dev(void)
 396  
 397  	BUILD_BUG_ON(sizeof(struct control_page) > PAGE_SIZE);
 398  
 399 +	BUILD_BUG_ON(sizeof(union np_flag) != sizeof(uint64_t));
 400 +
 401 +	BUILD_BUG_ON(offsetof(struct control_page, sched.raw)
 402 +		     != LITMUS_CP_OFFSET_SCHED);
 403 +	BUILD_BUG_ON(offsetof(struct control_page, irq_count)
 404 +		     != LITMUS_CP_OFFSET_IRQ_COUNT);
 405 +	BUILD_BUG_ON(offsetof(struct control_page, ts_syscall_start)
 406 +		     != LITMUS_CP_OFFSET_TS_SC_START);
 407 +	BUILD_BUG_ON(offsetof(struct control_page, irq_syscall_start)
 408 +		     != LITMUS_CP_OFFSET_IRQ_SC_START);
 409 +
 410  	printk("Initializing LITMUS^RT control device.\n");
 411  	err = misc_register(&litmus_ctrl_dev);
 412  	if (err)
 413 diff --git a/litmus/fdso.c b/litmus/fdso.c
 414 index cd85b9c..57813c0 100644
 415 --- a/litmus/fdso.c
 416 +++ b/litmus/fdso.c
 417 @@ -27,6 +27,7 @@ static const struct fdso_ops* fdso_ops[] = {
 418  	&generic_lock_ops, /* MPCP_VS_SEM */
 419  	&generic_lock_ops, /* DPCP_SEM */
 420  	&generic_lock_ops, /* PCP_SEM */
 421 +	&generic_lock_ops, /* DFLP_SEM */
 422  };
 423  
 424  static int fdso_create(void** obj_ref, obj_type_t type, void* __user config)
 425 @@ -166,14 +167,33 @@ static int put_od_entry(struct od_table_entry* od)
 426  	return 0;
 427  }
 428  
 429 +static long close_od_entry(struct od_table_entry *od)
 430 +{
 431 +	long ret;
 432 +
 433 +	/* Give the class a chance to reject the close. */
 434 +	ret = fdso_close(od);
 435 +	if (ret == 0)
 436 +		ret = put_od_entry(od);
 437 +
 438 +	return ret;
 439 +}
 440 +
 441 +#include <litmus/litmus.h>
 442 +
 443  void exit_od_table(struct task_struct* t)
 444  {
 445  	int i;
 446  
 447 +	if (is_realtime(t))
 448 +		printk("[%s] %s/%d/rt=%d (current: %s/%d/rt=%d)\n",
 449 +		       __FUNCTION__,
 450 +		       t->comm, t->pid, is_realtime(t),
 451 +		       current->comm, current->pid, is_realtime(current));
 452  	if (t->od_table) {
 453  		for (i = 0; i < MAX_OBJECT_DESCRIPTORS; i++)
 454  			if (t->od_table[i].used)
 455 -				put_od_entry(t->od_table + i);
 456 +				close_od_entry(t->od_table + i);
 457  		kfree(t->od_table);
 458  		t->od_table = NULL;
 459  	}
 460 @@ -287,11 +307,7 @@ asmlinkage long sys_od_close(int od)
 461  		return ret;
 462  
 463  
 464 -	/* give the class a chance to reject the close
 465 -	 */
 466 -	ret = fdso_close(t->od_table + od);
 467 -	if (ret == 0)
 468 -		ret = put_od_entry(t->od_table + od);
 469 +	ret = close_od_entry(t->od_table + od);
 470  
 471  	return ret;
 472  }
 473 diff --git a/litmus/fp_common.c b/litmus/fp_common.c
 474 index 31fc2db..964a472 100644
 475 --- a/litmus/fp_common.c
 476 +++ b/litmus/fp_common.c
 477 @@ -15,7 +15,7 @@
 478  #include <litmus/fp_common.h>
 479  
 480  /* fp_higher_prio -  returns true if first has a higher static priority
 481 - *                   than second. Deadline ties are broken by PID.
 482 + *                   than second. Ties are broken by PID.
 483   *
 484   * both first and second may be NULL
 485   */
 486 @@ -37,6 +37,9 @@ int fp_higher_prio(struct task_struct* first,
 487  	if (!first || !second)
 488  		return first && !second;
 489  
 490 +	if (!is_realtime(second_task))
 491 +		return 1;
 492 +
 493  #ifdef CONFIG_LITMUS_LOCKING
 494  
 495  	/* Check for inherited priorities. Change task
 496 @@ -51,33 +54,30 @@ int fp_higher_prio(struct task_struct* first,
 497  	 */
 498  	if (unlikely(is_priority_boosted(first_task))) {
 499  		/* first_task is boosted, how about second_task? */
 500 -		if (!is_priority_boosted(second_task) ||
 501 -		    lt_before(get_boost_start(first_task),
 502 -			      get_boost_start(second_task)))
 503 -			return 1;
 504 +		if (is_priority_boosted(second_task))
 505 +			/* break by priority point */
 506 +			return lt_before(get_boost_start(first_task),
 507 +					 get_boost_start(second_task));
 508  		else
 509 -			return 0;
 510 +			/* priority boosting wins. */
 511 +			return 1;
 512  	} else if (unlikely(is_priority_boosted(second_task)))
 513  		/* second_task is boosted, first is not*/
 514  		return 0;
 515  
 516  #endif
 517  
 518 +	/* Comparisons to itself are not expected; priority inheritance
 519 +	 * should also not cause this to happen. */
 520 +	BUG_ON(first_task == second_task);
 521  
 522 -	return !is_realtime(second_task)  ||
 523 -
 524 -		get_priority(first_task) < get_priority(second_task) ||
 525 -
 526 -		/* Break by PID.
 527 -		 */
 528 -		(get_priority(first_task) == get_priority(second_task) &&
 529 -	        (first_task->pid < second_task->pid ||
 530 -
 531 -		/* If the PIDs are the same then the task with the inherited
 532 -		 * priority wins.
 533 -		 */
 534 -		(first_task->pid == second_task->pid &&
 535 -		 !second->rt_param.inh_task)));
 536 +	if (get_priority(first_task) < get_priority(second_task))
 537 +		return 1;
 538 +	else if (get_priority(first_task) == get_priority(second_task))
 539 +		/* Break by PID. */
 540 +		return first_task->pid < second_task->pid;
 541 +	else
 542 +		return 0;
 543  }
 544  
 545  int fp_ready_order(struct bheap_node* a, struct bheap_node* b)
 546 diff --git a/litmus/ftdev.c b/litmus/ftdev.c
 547 index 06fcf4c..99bc39f 100644
 548 --- a/litmus/ftdev.c
 549 +++ b/litmus/ftdev.c
 550 @@ -230,13 +230,20 @@ static ssize_t ftdev_read(struct file *filp,
 551  			 * here with copied data because that data would get
 552  			 * lost if the task is interrupted (e.g., killed).
 553  			 */
 554 +			mutex_unlock(&ftdm->lock);
 555  			set_current_state(TASK_INTERRUPTIBLE);
 556 +
 557  			schedule_timeout(50);
 558 +
 559  			if (signal_pending(current)) {
 560  				if (err == 0)
 561  					/* nothing read yet, signal problem */
 562  					err = -ERESTARTSYS;
 563 -				break;
 564 +				goto out;
 565 +			}
 566 +			if (mutex_lock_interruptible(&ftdm->lock)) {
 567 +				err = -ERESTARTSYS;
 568 +				goto out;
 569  			}
 570  		} else if (copied < 0) {
 571  			/* page fault */
 572 diff --git a/litmus/litmus.c b/litmus/litmus.c
 573 index 8138432..a8203c2 100644
 574 --- a/litmus/litmus.c
 575 +++ b/litmus/litmus.c
 576 @@ -434,11 +434,11 @@ int switch_sched_plugin(struct sched_plugin* plugin)
 577  			goto out;
 578  		ret = plugin->activate_plugin();
 579  		if (0 != ret) {
 580 -			printk(KERN_INFO "Can't activate %s (%d).\n",
 581 +			printk("Can't activate %s (%d).\n",
 582  			       plugin->plugin_name, ret);
 583  			plugin = &linux_sched_plugin;
 584  		}
 585 -		printk(KERN_INFO "Switching to LITMUS^RT plugin %s.\n", plugin->plugin_name);
 586 +		printk("Switching to LITMUS^RT plugin %s.\n", plugin->plugin_name);
 587  		litmus = plugin;
 588  	} else
 589  		ret = -EBUSY;
 590 @@ -499,8 +499,17 @@ void exit_litmus(struct task_struct *dead_tsk)
 591  	}
 592  
 593  	/* main cleanup only for RT tasks */
 594 -	if (is_realtime(dead_tsk))
 595 +	if (is_realtime(dead_tsk)) {
 596 +		preempt_disable();
 597 +		printk("Tearing down real-time task %s/%d...\n",
 598 +		       dead_tsk->comm, dead_tsk->pid);
 599  		litmus_exit_task(dead_tsk);
 600 +		printk("Done with LITMUS^RT cleanup for %s/%d. "
 601 +		       "(%d remaning RT tasks)\n",
 602 +		       dead_tsk->comm, dead_tsk->pid,
 603 +		       atomic_read(&rt_task_count));
 604 +		preempt_enable();
 605 +	}
 606  }
 607  
 608  
 609 @@ -536,8 +545,6 @@ static int __init _init_litmus(void)
 610  	 */
 611  	printk("Starting LITMUS^RT kernel\n");
 612  
 613 -	BUILD_BUG_ON(sizeof(union np_flag) != sizeof(uint32_t));
 614 -
 615  	register_sched_plugin(&linux_sched_plugin);
 616  
 617  	bheap_node_cache    = KMEM_CACHE(bheap_node, SLAB_PANIC);
 618 diff --git a/litmus/locking.c b/litmus/locking.c
 619 index ca5a073..84a1d83 100644
 620 --- a/litmus/locking.c
 621 +++ b/litmus/locking.c
 622 @@ -1,3 +1,5 @@
 623 +#include <linux/sched.h>
 624 +#include <litmus/litmus.h>
 625  #include <litmus/fdso.h>
 626  
 627  #ifdef CONFIG_LITMUS_LOCKING
 628 @@ -70,6 +72,10 @@ asmlinkage long sys_litmus_lock(int lock_od)
 629  	struct od_table_entry* entry;
 630  	struct litmus_lock* l;
 631  
 632 +	TS_SYSCALL_IN_START;
 633 +
 634 +	TS_SYSCALL_IN_END;
 635 +
 636  	TS_LOCK_START;
 637  
 638  	entry = get_entry_for_od(lock_od);
 639 @@ -83,6 +89,8 @@ asmlinkage long sys_litmus_lock(int lock_od)
 640  	 * this into account when computing overheads. */
 641  	TS_LOCK_END;
 642  
 643 +	TS_SYSCALL_OUT_START;
 644 +
 645  	return err;
 646  }
 647  
 648 @@ -92,6 +100,10 @@ asmlinkage long sys_litmus_unlock(int lock_od)
 649  	struct od_table_entry* entry;
 650  	struct litmus_lock* l;
 651  
 652 +	TS_SYSCALL_IN_START;
 653 +
 654 +	TS_SYSCALL_IN_END;
 655 +
 656  	TS_UNLOCK_START;
 657  
 658  	entry = get_entry_for_od(lock_od);
 659 @@ -105,6 +117,8 @@ asmlinkage long sys_litmus_unlock(int lock_od)
 660  	 * account when computing overheads. */
 661  	TS_UNLOCK_END;
 662  
 663 +	TS_SYSCALL_OUT_START;
 664 +
 665  	return err;
 666  }
 667  
 668 @@ -154,6 +168,7 @@ out:
 669  	return passed;
 670  }
 671  
 672 +
 673  #else
 674  
 675  struct fdso_ops generic_lock_ops = {};
 676 diff --git a/litmus/preempt.c b/litmus/preempt.c
 677 index 5704d0b..6be2f26 100644
 678 --- a/litmus/preempt.c
 679 +++ b/litmus/preempt.c
 680 @@ -2,6 +2,7 @@
 681  
 682  #include <litmus/litmus.h>
 683  #include <litmus/preempt.h>
 684 +#include <litmus/trace.h>
 685  
 686  /* The rescheduling state of each processor.
 687   */
 688 @@ -47,6 +48,7 @@ void sched_state_ipi(void)
 689  		set_tsk_need_resched(current);
 690  		TRACE_STATE("IPI -> set_tsk_need_resched(%s/%d)\n",
 691  			    current->comm, current->pid);
 692 +		TS_SEND_RESCHED_END;
 693  	} else {
 694  		/* ignore */
 695  		TRACE_STATE("ignoring IPI in state %x (%s)\n",
 696 @@ -85,8 +87,10 @@ void litmus_reschedule(int cpu)
 697  	if (scheduled_transition_ok) {
 698  		if (smp_processor_id() == cpu)
 699  			set_tsk_need_resched(current);
 700 -		else
 701 +		else {
 702 +			TS_SEND_RESCHED_START(cpu);
 703  			smp_send_reschedule(cpu);
 704 +		}
 705  	}
 706  
 707  	TRACE_STATE("%s picked-ok:%d sched-ok:%d\n",
 708 diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c
 709 index d0b7966..1683d38 100644
 710 --- a/litmus/rt_domain.c
 711 +++ b/litmus/rt_domain.c
 712 @@ -331,12 +331,7 @@ void __add_release_on(rt_domain_t* rt, struct task_struct *task,
 713  	list_add(&tsk_rt(task)->list, &rt->tobe_released);
 714  	task->rt_param.domain = rt;
 715  
 716 -	/* start release timer */
 717 -	TS_SCHED2_START(task);
 718 -
 719  	arm_release_timer_on(rt, target_cpu);
 720 -
 721 -	TS_SCHED2_END(task);
 722  }
 723  #endif
 724  
 725 @@ -349,11 +344,6 @@ void __add_release(rt_domain_t* rt, struct task_struct *task)
 726  	list_add(&tsk_rt(task)->list, &rt->tobe_released);
 727  	task->rt_param.domain = rt;
 728  
 729 -	/* start release timer */
 730 -	TS_SCHED2_START(task);
 731 -
 732  	arm_release_timer(rt);
 733 -
 734 -	TS_SCHED2_END(task);
 735  }
 736  
 737 diff --git a/litmus/sched_litmus.c b/litmus/sched_litmus.c
 738 index 5a15ce9..1de8873 100644
 739 --- a/litmus/sched_litmus.c
 740 +++ b/litmus/sched_litmus.c
 741 @@ -194,6 +194,9 @@ static void dequeue_task_litmus(struct rq *rq, struct task_struct *p,
 742  
 743  static void yield_task_litmus(struct rq *rq)
 744  {
 745 +	TS_SYSCALL_IN_START;
 746 +	TS_SYSCALL_IN_END;
 747 +
 748  	BUG_ON(rq->curr != current);
 749  	/* sched_yield() is called to trigger delayed preemptions.
 750  	 * Thus, mark the current task as needing to be rescheduled.
 751 @@ -202,6 +205,8 @@ static void yield_task_litmus(struct rq *rq)
 752  	 */
 753  	clear_exit_np(current);
 754  	litmus_reschedule_local();
 755 +
 756 +	TS_SYSCALL_OUT_START;
 757  }
 758  
 759  /* Plugins are responsible for this.
 760 diff --git a/litmus/sched_pfp.c b/litmus/sched_pfp.c
 761 index 62be699..5a301e7 100644
 762 --- a/litmus/sched_pfp.c
 763 +++ b/litmus/sched_pfp.c
 764 @@ -55,7 +55,7 @@ static void preempt(pfp_domain_t *pfp)
 765  
 766  static unsigned int priority_index(struct task_struct* t)
 767  {
 768 -#ifdef CONFIG_LOCKING
 769 +#ifdef CONFIG_LITMUS_LOCKING
 770  	if (unlikely(t->rt_param.inh_task))
 771  		/* use effective priority */
 772  		t = t->rt_param.inh_task;
 773 @@ -76,23 +76,31 @@ static void pfp_release_jobs(rt_domain_t* rt, struct bheap* tasks)
 774  	struct task_struct* t;
 775  	struct bheap_node* hn;
 776  
 777 -	raw_spin_lock_irqsave(&pfp->slock, flags);
 778 -
 779  	while (!bheap_empty(tasks)) {
 780 +		raw_spin_lock_irqsave(&pfp->slock, flags);
 781 +
 782  		hn = bheap_take(fp_ready_order, tasks);
 783  		t = bheap2task(hn);
 784  		TRACE_TASK(t, "released (part:%d prio:%d)\n",
 785  			   get_partition(t), get_priority(t));
 786  		fp_prio_add(&pfp->ready_queue, t, priority_index(t));
 787 -	}
 788  
 789 -	/* do we need to preempt? */
 790 -	if (fp_higher_prio(fp_prio_peek(&pfp->ready_queue), pfp->scheduled)) {
 791 -		TRACE_CUR("preempted by new release\n");
 792 -		preempt(pfp);
 793 +		if (bheap_empty(tasks)) {
 794 +			/* do we need to preempt? */
 795 +			if (fp_higher_prio(fp_prio_peek(&pfp->ready_queue), pfp->scheduled)) {
 796 +				TRACE_CUR("preempted by new release\n");
 797 +				preempt(pfp);
 798 +			}
 799 +		}
 800 +
 801 +		raw_spin_unlock_irqrestore(&pfp->slock, flags);
 802  	}
 803 +}
 804  
 805 -	raw_spin_unlock_irqrestore(&pfp->slock, flags);
 806 +static void pfp_preempt_check(pfp_domain_t *pfp)
 807 +{
 808 +	if (fp_higher_prio(fp_prio_peek(&pfp->ready_queue), pfp->scheduled))
 809 +		preempt(pfp);
 810  }
 811  
 812  static void pfp_domain_init(pfp_domain_t* pfp,
 813 @@ -106,8 +114,7 @@ static void pfp_domain_init(pfp_domain_t* pfp,
 814  
 815  static void requeue(struct task_struct* t, pfp_domain_t *pfp)
 816  {
 817 -	if (t->state != TASK_RUNNING)
 818 -		TRACE_TASK(t, "requeue: !TASK_RUNNING\n");
 819 +	BUG_ON(!is_running(t));
 820  
 821  	set_rt_flags(t, RT_F_RUNNING);
 822  	if (is_released(t, litmus_clock()))
 823 @@ -123,6 +130,8 @@ static void job_completion(struct task_struct* t, int forced)
 824  
 825  	set_rt_flags(t, RT_F_SLEEP);
 826  	prepare_for_next_period(t);
 827 +	if (is_released(t, litmus_clock()))
 828 +		sched_trace_task_release(t);
 829  }
 830  
 831  static void pfp_tick(struct task_struct *t)
 832 @@ -217,6 +226,26 @@ static struct task_struct* pfp_schedule(struct task_struct * prev)
 833  		if (pfp->scheduled && !blocks  && !migrate)
 834  			requeue(pfp->scheduled, pfp);
 835  		next = fp_prio_take(&pfp->ready_queue);
 836 +		if (next == prev) {
 837 +			struct task_struct *t = fp_prio_peek(&pfp->ready_queue);
 838 +			TRACE_TASK(next, "next==prev sleep=%d oot=%d np=%d preempt=%d migrate=%d "
 839 +				   "boost=%d empty=%d prio-idx=%u prio=%u\n",
 840 +				   sleep, out_of_time, np, preempt, migrate,
 841 +				   is_priority_boosted(next),
 842 +				   t == NULL,
 843 +				   priority_index(next),
 844 +				   get_priority(next));
 845 +			if (t)
 846 +				TRACE_TASK(t, "waiter boost=%d prio-idx=%u prio=%u\n",
 847 +					   is_priority_boosted(t),
 848 +					   priority_index(t),
 849 +					   get_priority(t));
 850 +		}
 851 +		/* If preempt is set, we should not see the same task again. */
 852 +		BUG_ON(preempt && next == prev);
 853 +		/* Similarly, if preempt is set, then next may not be NULL,
 854 +		 * unless it's a migration. */
 855 +		BUG_ON(preempt && !migrate && next == NULL);
 856  	} else
 857  		/* Only override Linux scheduler if we have a real-time task
 858  		 * scheduled that needs to continue.
 859 @@ -291,7 +320,7 @@ static void pfp_task_new(struct task_struct * t, int on_rq, int running)
 860  	} else {
 861  		requeue(t, pfp);
 862  		/* maybe we have to reschedule */
 863 -		preempt(pfp);
 864 +		pfp_preempt_check(pfp);
 865  	}
 866  	raw_spin_unlock_irqrestore(&pfp->slock, flags);
 867  }
 868 @@ -337,8 +366,10 @@ static void pfp_task_wake_up(struct task_struct *task)
 869  	 * and won. Also, don't requeue if it is still queued, which can
 870  	 * happen under the DPCP due wake-ups racing with migrations.
 871  	 */
 872 -	if (pfp->scheduled != task)
 873 +	if (pfp->scheduled != task) {
 874  		requeue(task, pfp);
 875 +		pfp_preempt_check(pfp);
 876 +	}
 877  
 878  out_unlock:
 879  	raw_spin_unlock_irqrestore(&pfp->slock, flags);
 880 @@ -371,13 +402,24 @@ static void pfp_task_exit(struct task_struct * t)
 881  	rt_domain_t*		dom;
 882  
 883  	raw_spin_lock_irqsave(&pfp->slock, flags);
 884 +
 885 +	printk(KERN_ERR "[%s] %s/%d is exiting (part:%d / cpu:%d).\n",
 886 +	       __FUNCTION__, t->comm, t->pid, get_partition(t),
 887 +	       smp_processor_id());
 888 +
 889 +	if (t != current) {
 890 +		/* This currently doesn't work. */
 891 +		printk(KERN_ERR "[%s] task %s/%d is not current!\n",
 892 +		       __FUNCTION__, t->comm, t->pid);
 893 +	}
 894  	if (is_queued(t)) {
 895 -		BUG(); /* This currently doesn't work. */
 896 -		/* dequeue */
 897 -		dom  = task_dom(t);
 898 -		remove(dom, t);
 899 +		/* This currently doesn't work. */
 900 +		printk(KERN_ERR "[%s] task %s/%d is still queued!\n",
 901 +		       __FUNCTION__, t->comm, t->pid);
 902  	}
 903  	if (pfp->scheduled == t) {
 904 +		printk(KERN_ERR "[%s] task %s/%d is scheduled!\n",
 905 +		       __FUNCTION__, t->comm, t->pid);
 906  		pfp->scheduled = NULL;
 907  		preempt(pfp);
 908  	}
 909 @@ -455,17 +497,10 @@ static void boost_priority(struct task_struct* t, lt_t priority_point)
 910  	/* tie-break by protocol-specific priority point */
 911  	tsk_rt(t)->boost_start_time = priority_point;
 912  
 913 -	if (pfp->scheduled != t) {
 914 -		/* holder may be queued: first stop queue changes */
 915 -		raw_spin_lock(&pfp->domain.release_lock);
 916 -		if (is_queued(t) &&
 917 -		    /* If it is queued, then we need to re-order. */
 918 -		    bheap_decrease(fp_ready_order, tsk_rt(t)->heap_node) &&
 919 -		    /* If we bubbled to the top, then we need to check for preemptions. */
 920 -		    fp_preemption_needed(&pfp->ready_queue, pfp->scheduled))
 921 -				preempt(pfp);
 922 -		raw_spin_unlock(&pfp->domain.release_lock);
 923 -	} /* else: nothing to do since the job is not queued while scheduled */
 924 +	/* Priority boosting currently only takes effect for already-scheduled
 925 +	 * tasks. This is sufficient since priority boosting only kicks in as
 926 +	 * part of lock acquisitions. */
 927 +	BUG_ON(pfp->scheduled != t);
 928  
 929  	raw_spin_unlock_irqrestore(&pfp->slock, flags);
 930  }
 931 @@ -1521,6 +1556,211 @@ static struct litmus_lock* pfp_new_dpcp(int on_cpu)
 932  }
 933  
 934  
 935 +/* ******************** DFLP support ********************** */
 936 +
 937 +struct dflp_semaphore {
 938 +	struct litmus_lock litmus_lock;
 939 +
 940 +	/* current resource holder */
 941 +	struct task_struct *owner;
 942 +	int owner_cpu;
 943 +
 944 +	/* FIFO queue of waiting tasks */
 945 +	wait_queue_head_t wait;
 946 +
 947 +	/* where is the resource assigned to */
 948 +	int on_cpu;
 949 +};
 950 +
 951 +static inline struct dflp_semaphore* dflp_from_lock(struct litmus_lock* lock)
 952 +{
 953 +	return container_of(lock, struct dflp_semaphore, litmus_lock);
 954 +}
 955 +
 956 +int pfp_dflp_lock(struct litmus_lock* l)
 957 +{
 958 +	struct task_struct* t = current;
 959 +	struct dflp_semaphore *sem = dflp_from_lock(l);
 960 +	int from  = get_partition(t);
 961 +	int to    = sem->on_cpu;
 962 +	unsigned long flags;
 963 +	wait_queue_t wait;
 964 +	lt_t time_of_request;
 965 +
 966 +	if (!is_realtime(t))
 967 +		return -EPERM;
 968 +
 969 +	preempt_disable();
 970 +
 971 +	/* tie-break by this point in time */
 972 +	time_of_request = litmus_clock();
 973 +
 974 +	/* Priority-boost ourself *before* we suspend so that
 975 +	 * our priority is boosted when we resume. */
 976 +	boost_priority(t, time_of_request);
 977 +
 978 +	pfp_migrate_to(to);
 979 +
 980 +	/* Now on the right CPU, preemptions still disabled. */
 981 +
 982 +	spin_lock_irqsave(&sem->wait.lock, flags);
 983 +
 984 +	if (sem->owner) {
 985 +		/* resource is not free => must suspend and wait */
 986 +
 987 +		init_waitqueue_entry(&wait, t);
 988 +
 989 +		/* FIXME: interruptible would be nice some day */
 990 +		set_task_state(t, TASK_UNINTERRUPTIBLE);
 991 +
 992 +		__add_wait_queue_tail_exclusive(&sem->wait, &wait);
 993 +
 994 +		TS_LOCK_SUSPEND;
 995 +
 996 +		/* release lock before sleeping */
 997 +		spin_unlock_irqrestore(&sem->wait.lock, flags);
 998 +
 999 +		/* We depend on the FIFO order.  Thus, we don't need to recheck
1000 +		 * when we wake up; we are guaranteed to have the lock since
1001 +		 * there is only one wake up per release.
1002 +		 */
1003 +
1004 +		preempt_enable_no_resched();
1005 +
1006 +		schedule();
1007 +
1008 +		preempt_disable();
1009 +
1010 +		TS_LOCK_RESUME;
1011 +
1012 +		/* Since we hold the lock, no other task will change
1013 +		 * ->owner. We can thus check it without acquiring the spin
1014 +		 * lock. */
1015 +		BUG_ON(sem->owner != t);
1016 +	} else {
1017 +		/* it's ours now */
1018 +		sem->owner = t;
1019 +
1020 +		spin_unlock_irqrestore(&sem->wait.lock, flags);
1021 +	}
1022 +
1023 +	sem->owner_cpu = from;
1024 +
1025 +	preempt_enable();
1026 +
1027 +	return 0;
1028 +}
1029 +
1030 +int pfp_dflp_unlock(struct litmus_lock* l)
1031 +{
1032 +	struct task_struct *t = current, *next;
1033 +	struct dflp_semaphore *sem = dflp_from_lock(l);
1034 +	int err = 0;
1035 +	int home;
1036 +	unsigned long flags;
1037 +
1038 +	preempt_disable();
1039 +
1040 +	spin_lock_irqsave(&sem->wait.lock, flags);
1041 +
1042 +	if (sem->owner != t) {
1043 +		err = -EINVAL;
1044 +		spin_unlock_irqrestore(&sem->wait.lock, flags);
1045 +		goto out;
1046 +	}
1047 +
1048 +	/* check if there are jobs waiting for this resource */
1049 +	next = __waitqueue_remove_first(&sem->wait);
1050 +	if (next) {
1051 +		/* next becomes the resouce holder */
1052 +		sem->owner = next;
1053 +
1054 +		/* Wake up next. The waiting job is already priority-boosted. */
1055 +		wake_up_process(next);
1056 +	} else
1057 +		/* resource becomes available */
1058 +		sem->owner = NULL;
1059 +
1060 +	home = sem->owner_cpu;
1061 +
1062 +	spin_unlock_irqrestore(&sem->wait.lock, flags);
1063 +
1064 +	/* we lose the benefit of priority boosting */
1065 +	unboost_priority(t);
1066 +
1067 +	pfp_migrate_to(home);
1068 +
1069 +out:
1070 +	preempt_enable();
1071 +
1072 +	return err;
1073 +}
1074 +
1075 +int pfp_dflp_open(struct litmus_lock* l, void* __user config)
1076 +{
1077 +	struct dflp_semaphore *sem = dflp_from_lock(l);
1078 +	int cpu;
1079 +
1080 +	if (get_user(cpu, (int*) config))
1081 +		return -EFAULT;
1082 +
1083 +	/* make sure the resource location matches */
1084 +	if (cpu != sem->on_cpu)
1085 +		return -EINVAL;
1086 +
1087 +	return 0;
1088 +}
1089 +
1090 +int pfp_dflp_close(struct litmus_lock* l)
1091 +{
1092 +	struct task_struct *t = current;
1093 +	struct dflp_semaphore *sem = dflp_from_lock(l);
1094 +	int owner = 0;
1095 +
1096 +	preempt_disable();
1097 +
1098 +	if (sem->on_cpu == smp_processor_id())
1099 +		owner = sem->owner == t;
1100 +
1101 +	preempt_enable();
1102 +
1103 +	if (owner)
1104 +		pfp_dflp_unlock(l);
1105 +
1106 +	return 0;
1107 +}
1108 +
1109 +void pfp_dflp_free(struct litmus_lock* lock)
1110 +{
1111 +	kfree(dflp_from_lock(lock));
1112 +}
1113 +
1114 +static struct litmus_lock_ops pfp_dflp_lock_ops = {
1115 +	.close  = pfp_dflp_close,
1116 +	.lock   = pfp_dflp_lock,
1117 +	.open	= pfp_dflp_open,
1118 +	.unlock = pfp_dflp_unlock,
1119 +	.deallocate = pfp_dflp_free,
1120 +};
1121 +
1122 +static struct litmus_lock* pfp_new_dflp(int on_cpu)
1123 +{
1124 +	struct dflp_semaphore* sem;
1125 +
1126 +	sem = kmalloc(sizeof(*sem), GFP_KERNEL);
1127 +	if (!sem)
1128 +		return NULL;
1129 +
1130 +	sem->litmus_lock.ops = &pfp_dflp_lock_ops;
1131 +	sem->owner_cpu = NO_CPU;
1132 +	sem->owner   = NULL;
1133 +	sem->on_cpu  = on_cpu;
1134 +	init_waitqueue_head(&sem->wait);
1135 +
1136 +	return &sem->litmus_lock;
1137 +}
1138 +
1139 +
1140  /* **** lock constructor **** */
1141  
1142  
1143 @@ -1575,6 +1815,21 @@ static long pfp_allocate_lock(struct litmus_lock **lock, int type,
1144  			err = -ENOMEM;
1145  		break;
1146  
1147 +	case DFLP_SEM:
1148 +		/* Distributed FIFO Locking Protocol */
1149 +		if (get_user(cpu, (int*) config))
1150 +			return -EFAULT;
1151 +
1152 +		if (!cpu_online(cpu))
1153 +			return -EINVAL;
1154 +
1155 +		*lock = pfp_new_dflp(cpu);
1156 +		if (*lock)
1157 +			err = 0;
1158 +		else
1159 +			err = -ENOMEM;
1160 +		break;
1161 +
1162  	case SRP_SEM:
1163  		/* Baker's Stack Resource Policy */
1164  		srp = allocate_srp_semaphore();
1165 diff --git a/litmus/sched_psn_edf.c b/litmus/sched_psn_edf.c
1166 index b0c8126..8933e15 100644
1167 --- a/litmus/sched_psn_edf.c
1168 +++ b/litmus/sched_psn_edf.c
1169 @@ -133,6 +133,15 @@ static void unboost_priority(struct task_struct* t)
1170  
1171  #endif
1172  
1173 +static int psnedf_preempt_check(psnedf_domain_t *pedf)
1174 +{
1175 +	if (edf_preemption_needed(&pedf->domain, pedf->scheduled)) {
1176 +		preempt(pedf);
1177 +		return 1;
1178 +	} else
1179 +		return 0;
1180 +}
1181 +
1182  /* This check is trivial in partioned systems as we only have to consider
1183   * the CPU of the partition.
1184   */
1185 @@ -143,11 +152,7 @@ static int psnedf_check_resched(rt_domain_t *edf)
1186  	/* because this is a callback from rt_domain_t we already hold
1187  	 * the necessary lock for the ready queue
1188  	 */
1189 -	if (edf_preemption_needed(edf, pedf->scheduled)) {
1190 -		preempt(pedf);
1191 -		return 1;
1192 -	} else
1193 -		return 0;
1194 +	return psnedf_preempt_check(pedf);
1195  }
1196  
1197  static void job_completion(struct task_struct* t, int forced)
1198 @@ -299,7 +304,7 @@ static void psnedf_task_new(struct task_struct * t, int on_rq, int running)
1199  	} else {
1200  		requeue(t, edf);
1201  		/* maybe we have to reschedule */
1202 -		preempt(pedf);
1203 +		psnedf_preempt_check(pedf);
1204  	}
1205  	raw_spin_unlock_irqrestore(&pedf->slock, flags);
1206  }
1207 @@ -335,8 +340,10 @@ static void psnedf_task_wake_up(struct task_struct *task)
1208  	 * de-scheduling the task, i.e., wake_up() raced with schedule()
1209  	 * and won.
1210  	 */
1211 -	if (pedf->scheduled != task)
1212 +	if (pedf->scheduled != task) {
1213  		requeue(task, edf);
1214 +		psnedf_preempt_check(pedf);
1215 +	}
1216  
1217  	raw_spin_unlock_irqrestore(&pedf->slock, flags);
1218  	TRACE_TASK(task, "wake up done\n");
1219 diff --git a/litmus/sync.c b/litmus/sync.c
1220 index bf75fde..873b3ff 100644
1221 --- a/litmus/sync.c
1222 +++ b/litmus/sync.c
1223 @@ -16,63 +16,106 @@
1224  
1225  #include <litmus/sched_trace.h>
1226  
1227 -static DECLARE_COMPLETION(ts_release);
1228 +struct ts_release_wait {
1229 +	struct list_head list;
1230 +	struct completion completion;
1231 +	lt_t ts_release_time;
1232 +};
1233 +
1234 +#define DECLARE_TS_RELEASE_WAIT(symb)					\
1235 +	struct ts_release_wait symb =					\
1236 +	{								\
1237 +		LIST_HEAD_INIT(symb.list),				\
1238 +		COMPLETION_INITIALIZER_ONSTACK(symb.completion),	\
1239 +		0							\
1240 +	}
1241 +
1242 +static LIST_HEAD(task_release_list);
1243 +static DEFINE_MUTEX(task_release_lock);
1244  
1245  static long do_wait_for_ts_release(void)
1246  {
1247 -	long ret = 0;
1248 +	DECLARE_TS_RELEASE_WAIT(wait);
1249 +
1250 +	long ret = -ERESTARTSYS;
1251 +
1252 +	if (mutex_lock_interruptible(&task_release_lock))
1253 +		goto out;
1254 +
1255 +	list_add(&wait.list, &task_release_list);
1256  
1257 -	/* If the interruption races with a release, the completion object
1258 -	 * may have a non-zero counter. To avoid this problem, this should
1259 -	 * be replaced by wait_for_completion().
1260 -	 *
1261 -	 * For debugging purposes, this is interruptible for now.
1262 -	 */
1263 -	ret = wait_for_completion_interruptible(&ts_release);
1264 +	mutex_unlock(&task_release_lock);
1265  
1266 +	/* We are enqueued, now we wait for someone to wake us up. */
1267 +	ret = wait_for_completion_interruptible(&wait.completion);
1268 +
1269 +	if (!ret) {
1270 +		/* Completion succeeded, setup release. */
1271 +		litmus->release_at(current, wait.ts_release_time
1272 +				   + current->rt_param.task_params.phase
1273 +				   - current->rt_param.task_params.period);
1274 +		/* trigger advance to next job release at the programmed time */
1275 +		ret = complete_job();
1276 +	} else {
1277 +		/* We were interrupted, must cleanup list. */
1278 +		mutex_lock(&task_release_lock);
1279 +		if (!wait.completion.done)
1280 +			list_del(&wait.list);
1281 +		mutex_unlock(&task_release_lock);
1282 +	}
1283 +
1284 +out:
1285  	return ret;
1286  }
1287  
1288  int count_tasks_waiting_for_release(void)
1289  {
1290 -	unsigned long flags;
1291  	int task_count = 0;
1292  	struct list_head *pos;
1293  
1294 -	spin_lock_irqsave(&ts_release.wait.lock, flags);
1295 -	list_for_each(pos, &ts_release.wait.task_list) {
1296 +	mutex_lock(&task_release_lock);
1297 +
1298 +	list_for_each(pos, &task_release_list) {
1299  		task_count++;
1300  	}
1301 -	spin_unlock_irqrestore(&ts_release.wait.lock, flags);
1302 +
1303 +	mutex_unlock(&task_release_lock);
1304 +
1305  
1306  	return task_count;
1307  }
1308  
1309  static long do_release_ts(lt_t start)
1310  {
1311 -	int  task_count = 0;
1312 -	unsigned long flags;
1313 +	long  task_count = 0;
1314 +
1315  	struct list_head	*pos;
1316 -	struct task_struct 	*t;
1317 +	struct ts_release_wait	*wait;
1318  
1319 +	if (mutex_lock_interruptible(&task_release_lock)) {
1320 +		task_count = -ERESTARTSYS;
1321 +		goto out;
1322 +	}
1323  
1324 -	spin_lock_irqsave(&ts_release.wait.lock, flags);
1325  	TRACE("<<<<<< synchronous task system release >>>>>>\n");
1326 -
1327  	sched_trace_sys_release(&start);
1328 -	list_for_each(pos, &ts_release.wait.task_list) {
1329 -		t = (struct task_struct*) list_entry(pos,
1330 -						     struct __wait_queue,
1331 -						     task_list)->private;
1332 +
1333 +	task_count = 0;
1334 +	list_for_each(pos, &task_release_list) {
1335 +		wait = (struct ts_release_wait*)
1336 +			list_entry(pos, struct ts_release_wait, list);
1337 +
1338  		task_count++;
1339 -		litmus->release_at(t, start + t->rt_param.task_params.phase);
1340 -		sched_trace_task_release(t);
1341 +		wait->ts_release_time = start;
1342 +		complete(&wait->completion);
1343  	}
1344  
1345 -	spin_unlock_irqrestore(&ts_release.wait.lock, flags);
1346 +	/* clear stale list */
1347 +	INIT_LIST_HEAD(&task_release_list);
1348  
1349 -	complete_n(&ts_release, task_count);
1350 +	mutex_unlock(&task_release_lock);
1351  
1352 +out:
1353  	return task_count;
1354  }
1355  
1356 @@ -88,17 +131,22 @@ asmlinkage long sys_wait_for_ts_release(void)
1357  	return ret;
1358  }
1359  
1360 +#define ONE_MS 1000000
1361  
1362  asmlinkage long sys_release_ts(lt_t __user *__delay)
1363  {
1364  	long ret;
1365  	lt_t delay;
1366 +	lt_t start_time;
1367  
1368  	/* FIXME: check capabilities... */
1369  
1370  	ret = copy_from_user(&delay, __delay, sizeof(delay));
1371 -	if (ret == 0)
1372 -		ret = do_release_ts(litmus_clock() + delay);
1373 +	if (ret == 0) {
1374 +		/* round up to next larger integral millisecond */
1375 +		start_time = ((litmus_clock() / ONE_MS) + 1) * ONE_MS;
1376 +		ret = do_release_ts(start_time + delay);
1377 +	}
1378  
1379  	return ret;
1380  }
1381 diff --git a/litmus/trace.c b/litmus/trace.c
1382 index 3c35c52..7dbb98e 100644
1383 --- a/litmus/trace.c
1384 +++ b/litmus/trace.c
1385 @@ -18,6 +18,15 @@ static unsigned int ts_seq_no = 0;
1386  
1387  DEFINE_PER_CPU(atomic_t, irq_fired_count);
1388  
1389 +void ft_irq_fired(void)
1390 +{
1391 +	/* Only called with preemptions disabled.  */
1392 +	atomic_inc(&__get_cpu_var(irq_fired_count));
1393 +
1394 +	if (has_control_page(current))
1395 +		get_control_page(current)->irq_count++;
1396 +}
1397 +
1398  static inline void clear_irq_fired(void)
1399  {
1400  	atomic_set(&__raw_get_cpu_var(irq_fired_count), 0);
1401 @@ -34,77 +43,119 @@ static inline unsigned int get_and_clear_irq_fired(void)
1402  	return atomic_xchg(&__raw_get_cpu_var(irq_fired_count), 0);
1403  }
1404  
1405 -static inline void __save_irq_flags(struct timestamp *ts)
1406 +static inline void save_irq_flags(struct timestamp *ts, unsigned int irq_count)
1407  {
1408 -	unsigned int irq_count;
1409 -
1410 -	irq_count     = get_and_clear_irq_fired();
1411  	/* Store how many interrupts occurred. */
1412  	ts->irq_count = irq_count;
1413  	/* Extra flag because ts->irq_count overflows quickly. */
1414  	ts->irq_flag  = irq_count > 0;
1415 +
1416  }
1417  
1418 -static inline void __save_timestamp_cpu(unsigned long event,
1419 -					uint8_t type, uint8_t cpu)
1420 +static inline void write_timestamp(uint8_t event,
1421 +				   uint8_t type,
1422 +				   uint8_t cpu,
1423 +				   uint16_t pid_fragment,
1424 +				   unsigned int irq_count,
1425 +				   int record_irq,
1426 +				   int hide_irq,
1427 +				   uint64_t timestamp,
1428 +				   int record_timestamp)
1429  {
1430 +	unsigned long flags;
1431  	unsigned int seq_no;
1432  	struct timestamp *ts;
1433 +
1434 +	/* Avoid preemptions while recording the timestamp. This reduces the
1435 +	 * number of "out of order" timestamps in the stream and makes
1436 +	 * post-processing easier. */
1437 +
1438 +	local_irq_save(flags);
1439 +
1440  	seq_no = fetch_and_inc((int *) &ts_seq_no);
1441  	if (ft_buffer_start_write(trace_ts_buf, (void**)  &ts)) {
1442  		ts->event     = event;
1443  		ts->seq_no    = seq_no;
1444 -		ts->cpu       = cpu;
1445 +
1446  		ts->task_type = type;
1447 -		__save_irq_flags(ts);
1448 -		barrier();
1449 -		/* prevent re-ordering of ft_timestamp() */
1450 -		ts->timestamp = ft_timestamp();
1451 +		ts->pid	      = pid_fragment;
1452 +
1453 +		ts->cpu       = cpu;
1454 +
1455 +		if (record_irq)
1456 +			irq_count = get_and_clear_irq_fired();
1457 +
1458 +		save_irq_flags(ts, irq_count - hide_irq);
1459 +
1460 +		if (record_timestamp)
1461 +			timestamp = ft_timestamp();
1462 +
1463 +		ts->timestamp = timestamp;
1464  		ft_buffer_finish_write(trace_ts_buf, ts);
1465  	}
1466 +
1467 +	local_irq_restore(flags);
1468  }
1469  
1470  static void __add_timestamp_user(struct timestamp *pre_recorded)
1471  {
1472 +	unsigned long flags;
1473  	unsigned int seq_no;
1474  	struct timestamp *ts;
1475 +
1476 +
1477 +	local_irq_save(flags);
1478 +
1479  	seq_no = fetch_and_inc((int *) &ts_seq_no);
1480  	if (ft_buffer_start_write(trace_ts_buf, (void**)  &ts)) {
1481  		*ts = *pre_recorded;
1482  		ts->seq_no = seq_no;
1483 -		__save_irq_flags(ts);
1484 +		ts->cpu	   = raw_smp_processor_id();
1485 +	        save_irq_flags(ts, get_and_clear_irq_fired());
1486  		ft_buffer_finish_write(trace_ts_buf, ts);
1487  	}
1488 -}
1489  
1490 -static inline void __save_timestamp(unsigned long event,
1491 -				   uint8_t type)
1492 -{
1493 -	__save_timestamp_cpu(event, type, raw_smp_processor_id());
1494 +	local_irq_restore(flags);
1495  }
1496  
1497  feather_callback void save_timestamp(unsigned long event)
1498  {
1499 -	__save_timestamp(event, TSK_UNKNOWN);
1500 +	write_timestamp(event, TSK_UNKNOWN,
1501 +			raw_smp_processor_id(),
1502 +			current->pid,
1503 +			0, 1, 0,
1504 +			0, 1);
1505  }
1506  
1507  feather_callback void save_timestamp_def(unsigned long event,
1508  					 unsigned long type)
1509  {
1510 -	__save_timestamp(event, (uint8_t) type);
1511 +	write_timestamp(event, type,
1512 +			raw_smp_processor_id(),
1513 +			current->pid,
1514 +			0, 1, 0,
1515 +			0, 1);
1516  }
1517  
1518  feather_callback void save_timestamp_task(unsigned long event,
1519  					  unsigned long t_ptr)
1520  {
1521 -	int rt = is_realtime((struct task_struct *) t_ptr);
1522 -	__save_timestamp(event, rt ? TSK_RT : TSK_BE);
1523 +	struct task_struct *t = (struct task_struct *) t_ptr;
1524 +	int rt = is_realtime(t);
1525 +
1526 +	write_timestamp(event, rt ? TSK_RT : TSK_BE,
1527 +			raw_smp_processor_id(),
1528 +			t->pid,
1529 +			0, 1, 0,
1530 +			0, 1);
1531  }
1532  
1533  feather_callback void save_timestamp_cpu(unsigned long event,
1534  					 unsigned long cpu)
1535  {
1536 -	__save_timestamp_cpu(event, TSK_UNKNOWN, cpu);
1537 +	write_timestamp(event, TSK_UNKNOWN, cpu, current->pid,
1538 +			0, 1, 0,
1539 +			0, 1);
1540  }
1541  
1542  feather_callback void save_task_latency(unsigned long event,
1543 @@ -112,20 +163,44 @@ feather_callback void save_task_latency(unsigned long event,
1544  {
1545  	lt_t now = litmus_clock();
1546  	lt_t *when = (lt_t*) when_ptr;
1547 -	unsigned int seq_no;
1548 -	int cpu = raw_smp_processor_id();
1549 -	struct timestamp *ts;
1550  
1551 -	seq_no = fetch_and_inc((int *) &ts_seq_no);
1552 -	if (ft_buffer_start_write(trace_ts_buf, (void**)  &ts)) {
1553 -		ts->event     = event;
1554 -		ts->timestamp = now - *when;
1555 -		ts->seq_no    = seq_no;
1556 -		ts->cpu       = cpu;
1557 -		ts->task_type = TSK_RT;
1558 -		__save_irq_flags(ts);
1559 -		ft_buffer_finish_write(trace_ts_buf, ts);
1560 -	}
1561 +	write_timestamp(event, TSK_RT, raw_smp_processor_id(), 0,
1562 +			0, 1, 0,
1563 +			now - *when, 0);
1564 +}
1565 +
1566 +/* fake timestamp to user-reported time */
1567 +feather_callback void save_timestamp_time(unsigned long event,
1568 +			 unsigned long ptr)
1569 +{
1570 +	uint64_t* time = (uint64_t*) ptr;
1571 +
1572 +	write_timestamp(event, is_realtime(current) ? TSK_RT : TSK_BE,
1573 +			raw_smp_processor_id(), current->pid,
1574 +			0, 1, 0,
1575 +			*time, 0);
1576 +}
1577 +
1578 +/* Record user-reported IRQ count */
1579 +feather_callback void save_timestamp_irq(unsigned long event,
1580 +			unsigned long irq_counter_ptr)
1581 +{
1582 +	uint64_t* irqs = (uint64_t*) irq_counter_ptr;
1583 +
1584 +	write_timestamp(event, is_realtime(current) ? TSK_RT : TSK_BE,
1585 +			raw_smp_processor_id(), current->pid,
1586 +			*irqs, 0, 0,
1587 +			0, 1);
1588 +}
1589 +
1590 +/* Suppress one IRQ from the irq count. Used by TS_SEND_RESCHED_END, which is
1591 + * called from within an interrupt that is expected. */
1592 +feather_callback void save_timestamp_hide_irq(unsigned long event)
1593 +{
1594 +	write_timestamp(event, is_realtime(current) ? TSK_RT : TSK_BE,
1595 +			raw_smp_processor_id(), current->pid,
1596 +			0, 1, 1,
1597 +			0, 1);
1598  }
1599  
1600  /******************************************************************************/

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2015-06-04 21:22:59, 244.8 KB) [[attachment:MC2-liblitmus-imx6-rtss15.patch]]
  • [get | view] (2016-05-12 14:35:37, 51.9 KB) [[attachment:MC2-liblitmus-rtss16.patch]]
  • [get | view] (2016-05-12 14:36:06, 190.4 KB) [[attachment:MC2-litmus-rt-rtss16.patch]]
  • [get | view] (2015-07-19 10:27:52, 1119.9 KB) [[attachment:MC2-litmut-rt-imx6-rtss15.patch]]
  • [get | view] (2014-05-27 20:46:19, 58.3 KB) [[attachment:MC2_liblitmus_ipdps15.patch]]
  • [get | view] (2014-05-27 20:45:43, 1044.3 KB) [[attachment:MC2_litmusrt_ipdps15.patch]]
  • [get | view] (2017-04-07 21:48:09, 6099.5 KB) [[attachment:buff_sharing.tar]]
  • [get | view] (2015-01-08 14:20:07, 61.0 KB) [[attachment:feather-trace-patch-against-sched-deadline-v8.patch]]
  • [get | view] (2014-04-01 23:10:10, 38.9 KB) [[attachment:gedf-mp-rtas14.patch]]
  • [get | view] (2012-03-02 20:13:59, 1.9 KB) [[attachment:gpu-klmirqd-liblitmus-rt-ecrts12.patch]]
  • [get | view] (2012-03-02 20:14:25, 389.8 KB) [[attachment:gpu-klmirqd-litmus-rt-ecrts12.patch]]
  • [get | view] (2012-05-26 21:41:34, 418.0 KB) [[attachment:gpusync-rtss12.patch]]
  • [get | view] (2012-05-26 21:42:20, 8.6 KB) [[attachment:gpusync_liblitmus-rtss12.patch]]
  • [get | view] (2013-05-21 15:32:08, 208.6 KB) [[attachment:gpusync_rtss13_liblitmus.patch]]
  • [get | view] (2013-05-21 15:31:32, 779.5 KB) [[attachment:gpusync_rtss13_litmus.patch]]
  • [get | view] (2012-05-26 21:42:41, 71.4 KB) [[attachment:klt_tracker_v1.0.litmus.tgz]]
  • [get | view] (2016-10-13 21:14:05, 19.6 KB) [[attachment:liblitmus-rtas17.patch]]
  • [get | view] (2017-05-01 20:46:22, 90.0 KB) [[attachment:liblitmus-rtns17.patch]]
  • [get | view] (2018-12-11 01:38:53, 49.1 KB) [[attachment:liblitmus-semi-part-with-edfos.patch]]
  • [get | view] (2017-10-09 19:16:09, 304.0 KB) [[attachment:litmus-rt-os-isolation.patch]]
  • [get | view] (2016-10-13 21:13:27, 207.6 KB) [[attachment:litmus-rt-rtas17.patch]]
  • [get | view] (2017-05-01 20:46:40, 207.6 KB) [[attachment:litmus-rt-rtns17.patch]]
  • [get | view] (2018-12-11 01:39:04, 100.5 KB) [[attachment:litmus-rt-semi-part-with-edfos.patch]]
  • [get | view] (2018-06-26 04:31:48, 7.0 KB) [[attachment:mc2_liblitmus_2015.1-rtns18.patch]]
  • [get | view] (2018-06-26 04:31:33, 292.7 KB) [[attachment:mc2_litmus-rt_2015.1-rtns18.patch]]
  • [get | view] (2017-05-01 20:45:10, 2596.9 KB) [[attachment:mcp_study.zip]]
  • [get | view] (2013-07-13 14:11:53, 58.0 KB) [[attachment:omip-ecrts13.patch]]
  • [get | view] (2014-02-19 21:48:33, 17.2 KB) [[attachment:pgmrt-liblitmus-ecrts14.patch]]
  • [get | view] (2014-02-19 21:47:57, 87.8 KB) [[attachment:pgmrt-litmusrt-ecrts14.patch]]
  • [get | view] (2015-01-08 14:22:32, 61.0 KB) [[attachment:sched-deadline-v8-feather-trace-rtas14.patch]]
  • [get | view] (2018-06-26 04:32:13, 2545.1 KB) [[attachment:sched_study_rtns2018.tar.gz]]
  • [get | view] (2017-04-07 21:53:39, 5969.5 KB) [[attachment:seminal.tar]]
  • [get | view] (2017-04-07 21:51:13, 6064.0 KB) [[attachment:shared_libraries.tar]]
  • [get | view] (2013-07-13 13:58:25, 42.7 KB) [[attachment:tracing-and-dflp-rtas13.patch]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.