public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* garbage returned from do_gettimeofday
@ 2002-09-18 23:00 anton wilson
  2002-09-19 15:53 ` anton wilson
  0 siblings, 1 reply; 4+ messages in thread
From: anton wilson @ 2002-09-18 23:00 UTC (permalink / raw)
  To: linux-kernel


I'm using do_gettimeofday in the scheduler, once per schedule.
Ocassioanlly, i'll get what seems to be a random garbage number.
For example:

tv_sec     tv_usec 
1032378775 627501
1032378775 627521
3433001412 1
1032378775 627573
1032378775 627617
1032378775 627638

or

1032379233 253008
1032379233 253028
3387638236 1
1032379233 253068
1032379233 253125


The garbage number tv_sec always seems to begin with a 3 and is followed by 9 
digits. The tv_usec garbage number is always 1.


Most of the code I changed in sched.c follows. It attempts to allow a normal
process to run in place of a SCHED_RR process with a certain limited 
frequency and within a certain window of time. A starvation threshold is 
added which allows a normal process to run disregarding the requested window. 
The patch is very constrained in it's application. It's for a program in 
which a fifo thread runs once every millisecond, and round robin threads take 
up the remainder of the time.

=====================================================

#define NORM_THRESH             1000             
#define NORM_STARVE             20000
#define NORM_WINDOW             800   

#ifdef CONFIG_SCHED_RR_NONSTARVE

int inline rr_should_yield(runqueue_t *rq, struct timeval now)
{
   unsigned long normdiff, secdiff, fifodiff;
   
   secdiff = now.tv_sec - rq->last_normal.tv_sec;
   normdiff = now.tv_usec - ((secdiff * 1000000) + rq->last_normal.tv_usec);

   if( normdiff > NORM_STARVE)
     {
       return 1;
     }

   secdiff = now.tv_sec - rq->last_fifo.tv_sec;
   fifodiff = now.tv_usec - ((secdiff * 1000000) + rq->last_fifo.tv_usec);
   
 
   if( (normdiff > NORM_THRESH) && (fifodiff > NORM_WINDOW) )
     {
       return 1;
     }
 
   return 0;   

}

#endif /*CONFIG_RT_NONSTARVE*/
/*
 * 'schedule()' is the main scheduler function.
 */
asmlinkage void schedule(void)
{
	task_t *prev, *next;
	runqueue_t *rq;
	prio_array_t *array;
	list_t *queue;
	int idx;
#ifdef CONFIG_SCHED_RR_NONSTARVE
        struct timeval now; /* schedule timestamp */
        int idx2;
#endif
#ifdef CONFIG_RT_SWITCH_PRINT
        int policy1;
        int policy2;
        struct timeval tv;
	unsigned long flags;
        int allowed = 0;
#endif


	if (unlikely(in_interrupt()))
		BUG();

need_resched:
	preempt_disable();
	prev = current;
	rq = this_rq();

	release_kernel_lock(prev, smp_processor_id());
	prev->sleep_timestamp = jiffies;
	spin_lock_irq(&rq->lock);
        
	/*
	 * if entering from preempt_schedule, off a kernel preemption,
	 * go straight to picking the next task.
	 */
	if (unlikely(preempt_get_count() & PREEMPT_ACTIVE))
		goto pick_next_task;

#if CONFIG_RR_RESCHED_SWITCH || CONFIG_SCHED_RR_NONSTARVE
        /*
         * Move a SCHED_RR task to end of RQ each time schedule is called
         */

        do_gettimeofday(&now); 

        if (prev->policy == SCHED_RR){

#ifdef CONFIG_SCHED_RR_NONSTARVE
            if(unlikely(rq->non_rt_starving)){

                  /* if all normal processes are expired
                   * we dequeue the round robin processes
                   * instead of putting them at the end
                   * of their queue in the active array
                   * This will trigger a active/expired switch
                   * eventually
                   */
                  printk("moving RR to expired\n");
              /*    dequeue_task(prev, rq->active);
                  prev->first_time_slice = 0;
                  enqueue_task(prev, rq->expired);*/
                  //rq->expired_timestamp = jiffies;
                  goto pick_next_task;
             }
#endif /*CONFIG_SCHED_RR_NONSTARVE*/

#ifdef CONFIG_RR_RESCHED_SWITCH
             dequeue_task(prev, rq->active);
             enqueue_task(prev, rq->active);
#endif /*CONFIG_RR_RESCHED_SWITCH*/

out_rr_move:
        }
#endif /*CONFIG_RR_RESCHED_SWITCH || CONFIG_SCHED_RR_NONSTARVE*/


	switch (prev->state) {
	case TASK_INTERRUPTIBLE:
		if (unlikely(signal_pending(prev))) {
			prev->state = TASK_RUNNING;
			break;
		}
	default:
		deactivate_task(prev, rq);
	case TASK_RUNNING:
		;
	}
pick_next_task:
	if (unlikely(!rq->nr_running)) {
#if CONFIG_SMP
		load_balance(rq, 1);
		if (rq->nr_running)
			goto pick_next_task;
#endif
		/*
		 * Pick a task from the batch queue if available.
		 */
		if (rq->nr_batch) {
			list_t *tmp = rq->batch_queue.next;

			next = list_entry(tmp, task_t, run_list);
			activate_batch_task(next, rq);
		} else
			next = rq->idle;
		rq->expired_timestamp = 0;
		goto switch_tasks;
	}

	array = rq->active;
	if (unlikely(!array->nr_active)) {
		/*
		 * Switch the active and expired arrays.
		 */
		rq->active = rq->expired;
		rq->expired = array;
		array = rq->active;
		rq->expired_timestamp = 0;
#ifdef CONFIG_SCHED_RR_NONSTARVE
		if(rq->non_rt_starving){
                rq->non_rt_starving = 0;
		printk("exchange!\n");
		}
#endif /* CONFIG_SCHED_RR_NONSTARVE*/
	}

	idx = sched_find_first_bit(array->bitmap);
	queue = array->queue + idx;
	next = list_entry(queue->next, task_t, run_list);


#ifdef CONFIG_SCHED_RR_NONSTARVE
        /*
         * if SCHED_RR task should yeild and next task is SCHED_RR
         *               let a SCHED_NORMAL process take the CPU
         */

        switch (next->policy){
           case SCHED_FIFO:
                rq->last_fifo = now;      
                break;
           case SCHED_NORMAL:
                rq->last_normal = now;
                break;
           case SCHED_RR:
               if( rr_should_yield(rq, now) ){

                    /*find non RT process*/
                    idx2 = find_next_bit(array->bitmap, MAX_PRIO,MAX_RT_PRIO);

                    /*if nothing found, they must be expired*/
                    if(idx2 == MAX_PRIO && EXPIRED_STARVING(rq)){
                       rq->non_rt_starving = 1;
	               goto switch_tasks;
		     }
			
                   /*use process list at idx2*/
                    if(idx2 < MAX_PRIO){
                      queue = array->queue + idx2;
                      next = list_entry(queue->next, task_t, run_list);
                      rq->last_normal = now;
                      printk("allowing %d\n", next->pid);     
                      allowed = 1;
                     }
                 }
           }
        

#endif /*CONFIG_SCHED_RR_NONSTARVE*/

switch_tasks:

#ifdef CONFIG_RT_SWITCH_PRINT

        policy1 = prev->policy;
        policy2 = next->policy;

        if(allowed || (policy1 != SCHED_NORMAL || policy2 != SCHED_NORMAL)){

             switch (policy1){
                case SCHED_FIFO:
                printk("[{%d} ",prev->pid);
                break;
                case SCHED_RR:
                printk("[(%d) ",prev->pid);
                break;
                default:
                printk("[%d ",prev->pid);
                }

             switch (policy2){
                case SCHED_FIFO:
                printk("{%d} - %lu %lu]\n",next->pid, now.tv_sec, 
now.tv_usec);
                break;
                case SCHED_RR:
                printk("(%d) - %lu %lu]",next->pid, now.tv_sec, now.tv_usec);
                break;
                default:
                printk("%d - %lu %lu]",next->pid, now.tv_sec, now.tv_usec);
                }
#ifdef CONFIG_RT_PRINT_DEFAULT
	     printk("\n");	
#endif /* CONFIG_RT_PRINT_DEFAULT*/


        }
#endif /*CONFIG_RT_SWITCH_PRINT */

	prefetch(next);
	clear_tsk_need_resched(prev);

	if (likely(prev != next)) {
		rq->nr_switches++;
		rq->curr = next;
	
		prepare_arch_switch(rq, next);
		prev = context_switch(prev, next);
		barrier();
		rq = this_rq();
		finish_arch_switch(rq, prev);
	} else
		spin_unlock_irq(&rq->lock);

	reacquire_kernel_lock(current);
	preempt_enable_no_resched();
	if (need_resched())
		goto need_resched;
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-09-20 16:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-09-18 23:00 garbage returned from do_gettimeofday anton wilson
2002-09-19 15:53 ` anton wilson
2002-09-19 22:34   ` anton wilson
2002-09-20 16:43     ` george anzinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox