Warning, cross-references for /kernel/sched/sleep.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "arch/i386.h"
0019 #include "arch/i386-div64.h"
0020 #include "kernel.h"
0021 #include "smp/smp.h"
0022 #include "smp/apic.h"
0023 #include "util/printf.h"
0024 #include "sched/sched.h"
0025
0026
0027
0028
0029
0030 #ifdef DEBUG_SCHED_SLEEP
0031 #define DLOG(fmt,...) DLOG_PREFIX("sched-sleep",fmt,##__VA_ARGS__)
0032 #else
0033 #define DLOG(fmt,...) ;
0034 #endif
0035
0036 static task_id sleepqueue = 0;
0037
0038 extern uint64 tsc_freq;
0039
0040 static inline uint64
0041 compute_finish (uint32 usec)
0042 {
0043 uint64 ticks;
0044 uint64 start;
0045
0046 RDTSC (start);
0047
0048 ticks = div64_64 (tsc_freq * (u64) usec, 1000000LL);
0049
0050 return start + ticks;
0051 }
0052
0053
0054 extern void
0055 sched_usleep (uint32 usec)
0056 {
0057 if (mp_enabled) {
0058 task_id sel;
0059 quest_tss *tssp;
0060 uint64 finish = compute_finish (usec);
0061 #ifdef DEBUG_SCHED_SLEEP
0062 u64 now; RDTSC (now);
0063 #endif
0064 sel = str ();
0065 DLOG ("task 0x%x sleeping for %d usec (0x%llX -> 0x%llX)",
0066 sel, usec, now, finish);
0067 tssp = lookup_TSS (sel);
0068 tssp->time = finish;
0069 queue_append (&sleepqueue, sel);
0070
0071 schedule ();
0072 } else
0073
0074 tsc_delay_usec (usec);
0075 }
0076
0077
0078 extern void
0079 tsc_delay_usec (uint32 usec)
0080 {
0081 uint64 value, finish;
0082
0083 finish = compute_finish (usec);
0084 for (;;) {
0085 RDTSC (value);
0086 if (value >= finish)
0087 break;
0088 asm volatile ("pause");
0089 }
0090 }
0091
0092
0093 extern void
0094 process_sleepqueue (void)
0095 {
0096 uint64 now;
0097 task_id *q, next;
0098 quest_tss *tssp;
0099
0100 RDTSC (now);
0101
0102 if (sleepqueue == 0)
0103 return;
0104
0105 q = &sleepqueue;
0106 tssp = lookup_TSS (sleepqueue);
0107 DLOG ("process_sleepqueue 0x%llX", now);
0108 for (;;) {
0109
0110 next = tssp->next;
0111
0112 if (tssp->time <= now) {
0113 DLOG ("waking task 0x%x (0x%llX <= 0x%llX)", *q, tssp->time, now);
0114
0115 wakeup (*q);
0116
0117 *q = next;
0118 tssp->time = 0;
0119 } else
0120 q = &tssp->next;
0121
0122
0123 if (next == 0)
0124 break;
0125 tssp = lookup_TSS (*q);
0126 }
0127 }
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138