Browse Source

[Timers] Initialise timers on first use

Timers are sometimes required before the call to initialise(), so we
cannot rely on initialise() to set up the timers before use.

Also fix a potential integer overflow issue in generic_currticks_udelay()
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
070cbebc26
2 changed files with 26 additions and 27 deletions
  1. 25
    27
      src/core/timer.c
  2. 1
    0
      src/include/gpxe/timer.h

+ 25
- 27
src/core/timer.c View File

@@ -20,7 +20,6 @@
20 20
 
21 21
 #include <stddef.h>
22 22
 #include <assert.h>
23
-#include <gpxe/init.h>
24 23
 #include <gpxe/timer.h>
25 24
 
26 25
 static struct timer ts_table[0]
@@ -28,34 +27,39 @@ static struct timer ts_table[0]
28 27
 static struct timer ts_table_end[0]
29 28
 	__table_end ( struct timer, timers );
30 29
 
31
-
32
-static struct timer *used_ts = NULL;
33
-
34 30
 /*
35 31
  * This function may be used in custom timer driver.
36 32
  *
37 33
  * This udelay implementation works well if you've got a
38 34
  * fast currticks().
39 35
  */
40
-void generic_currticks_udelay(unsigned int usecs)
41
-{
42
-	tick_t t;
43
-
44
-	t = currticks();
45
-	while (t + usecs > currticks())
46
-		; /* xxx: Relax the cpu some way. */
36
+void generic_currticks_udelay ( unsigned int usecs ) {
37
+	tick_t start;
38
+	tick_t elapsed;
39
+	
40
+	start = currticks();
41
+	do {
42
+		/* xxx: Relax the cpu some way. */
43
+		elapsed = ( currticks() - start );
44
+	} while ( elapsed < usecs );
47 45
 }
48 46
 
47
+/**
48
+ * Identify timer source
49
+ *
50
+ * @ret timer		Timer source
51
+ */
52
+static struct timer * timer ( void ) {
53
+	static struct timer *ts = NULL;
49 54
 
50
-static void timer_init(void)
51
-{
52
-	struct timer *ts;
55
+	/* If we have a timer, use it */
56
+	if ( ts )
57
+		return ts;
53 58
 
54
-	for (ts = ts_table; ts < ts_table_end; ts++) {
55
-		if ( ts->init() == 0 ) {
56
-			used_ts = ts;
57
-			return;
58
-		}
59
+	/* Scan for a usable timer */
60
+	for ( ts = ts_table ; ts < ts_table_end ; ts++ ) {
61
+		if ( ts->init() == 0 )
62
+			return ts;
59 63
 	}
60 64
 
61 65
 	/* No timer found; we cannot continue */
@@ -63,10 +67,6 @@ static void timer_init(void)
63 67
 	while ( 1 ) {};
64 68
 }
65 69
 
66
-struct init_fn ts_init_fn __init_fn ( INIT_NORMAL ) = {
67
-	.initialise = timer_init,
68
-};
69
-
70 70
 /**
71 71
  * Read current time
72 72
  *
@@ -74,9 +74,8 @@ struct init_fn ts_init_fn __init_fn ( INIT_NORMAL ) = {
74 74
  */
75 75
 tick_t currticks ( void ) {
76 76
 	tick_t ct;
77
-	assert(used_ts);
78 77
 
79
-	ct = used_ts->currticks();
78
+	ct = timer()->currticks();
80 79
 	DBG ( "currticks: %ld.%06ld seconds\n",
81 80
 	      ct / USECS_IN_SEC, ct % USECS_IN_SEC );
82 81
 
@@ -89,8 +88,7 @@ tick_t currticks ( void ) {
89 88
  * @v usecs	Time to delay, in microseconds
90 89
  */
91 90
 void udelay ( unsigned int usecs ) {
92
-	assert(used_ts);
93
-	used_ts->udelay ( usecs );
91
+	timer()->udelay ( usecs );
94 92
 }
95 93
 
96 94
 /**

+ 1
- 0
src/include/gpxe/timer.h View File

@@ -2,6 +2,7 @@
2 2
 #define GPXE_TIMER_H
3 3
 
4 4
 #include <stddef.h>
5
+#include <gpxe/tables.h>
5 6
 
6 7
 typedef unsigned long tick_t;
7 8
 

Loading…
Cancel
Save