kern

diff src/timer.c @ 55:88a6c4e192f9

Fixed most important task switching bugs. Now it seems that I can switch in and out of user space reliably.
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 15 Aug 2011 04:03:39 +0300
parents b1e8c8251884
children 0be4615594df
line diff
     1.1 --- a/src/timer.c	Sun Aug 14 16:57:23 2011 +0300
     1.2 +++ b/src/timer.c	Mon Aug 15 04:03:39 2011 +0300
     1.3 @@ -45,10 +45,6 @@
     1.4  
     1.5  struct timer_event {
     1.6  	int dt;	/* remaining ticks delta from the previous event */
     1.7 -
     1.8 -	void (*callback)(void*);
     1.9 -	void *cbarg;
    1.10 -
    1.11  	struct timer_event *next;
    1.12  };
    1.13  
    1.14 @@ -79,24 +75,21 @@
    1.15  	interrupt(IRQ_TO_INTR(0), intr_handler);
    1.16  }
    1.17  
    1.18 -int start_timer(unsigned long msec, timer_func_t cbfunc, void *cbarg)
    1.19 +void sleep(unsigned long msec)
    1.20  {
    1.21  	int ticks, tsum, istate;
    1.22  	struct timer_event *ev, *node;
    1.23  
    1.24 -	printf("start_timer(%lu)\n", msec);
    1.25 +	printf("sleep(%lu)\n", msec);
    1.26  
    1.27  	if((ticks = MSEC_TO_TICKS(msec)) <= 0) {
    1.28 -		cbfunc(cbarg);
    1.29 -		return 0;
    1.30 +		return;
    1.31  	}
    1.32  
    1.33  	if(!(ev = malloc(sizeof *ev))) {
    1.34 -		printf("start_timer: failed to allocate timer_event structure\n");
    1.35 -		return -1;
    1.36 +		printf("sleep: failed to allocate timer_event structure\n");
    1.37 +		return;
    1.38  	}
    1.39 -	ev->callback = cbfunc;
    1.40 -	ev->cbarg = cbarg;
    1.41  
    1.42  	istate = get_intr_state();
    1.43  	disable_intr();
    1.44 @@ -110,29 +103,30 @@
    1.45  		if(ev->next) {
    1.46  			ev->next->dt -= ticks;
    1.47  		}
    1.48 -		set_intr_state(istate);
    1.49 -		return 0;
    1.50 -	}
    1.51 +	} else {
    1.52  
    1.53 -	tsum = evlist->dt;
    1.54 -	node = evlist;
    1.55 +		tsum = evlist->dt;
    1.56 +		node = evlist;
    1.57  
    1.58 -	while(node->next && ticks > tsum + node->next->dt) {
    1.59 -		tsum += node->next->dt;
    1.60 -		node = node->next;
    1.61 -	}
    1.62 +		while(node->next && ticks > tsum + node->next->dt) {
    1.63 +			tsum += node->next->dt;
    1.64 +			node = node->next;
    1.65 +		}
    1.66  
    1.67 -	ev->next = node->next;
    1.68 -	node->next = ev;
    1.69 +		ev->next = node->next;
    1.70 +		node->next = ev;
    1.71  
    1.72 -	/* fix the relative times */
    1.73 -	ev->dt = ticks - tsum;
    1.74 -	if(ev->next) {
    1.75 -		ev->next->dt -= ev->dt;
    1.76 +		/* fix the relative times */
    1.77 +		ev->dt = ticks - tsum;
    1.78 +		if(ev->next) {
    1.79 +			ev->next->dt -= ev->dt;
    1.80 +		}
    1.81  	}
    1.82  
    1.83  	set_intr_state(istate);
    1.84 -	return 0;
    1.85 +
    1.86 +	/* wait on the address of this timer event */
    1.87 +	wait(ev);
    1.88  }
    1.89  
    1.90  /* This will be called by the interrupt dispatcher approximately
    1.91 @@ -160,17 +154,15 @@
    1.92  			evlist = evlist->next;
    1.93  
    1.94  			printf("timer going off!!!\n");
    1.95 -			ev->callback(ev->cbarg);
    1.96 +			/* wake up all processes waiting on this address */
    1.97 +			wakeup(ev);
    1.98  			free(ev);
    1.99  		}
   1.100  	}
   1.101  
   1.102  	if((cur_proc = get_current_proc())) {
   1.103 +		/* if the timeslice of this process has expire, call the scheduler */
   1.104  		if(--cur_proc->ticks_left <= 0) {
   1.105 -			/* since schedule will not return, we have to notify
   1.106 -			 * the PIC that we're done with the IRQ handling
   1.107 -			 */
   1.108 -			end_of_irq(INTR_TO_IRQ(inum));
   1.109  			schedule();
   1.110  		}
   1.111  	}