wheel.h
3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
* Copyright (C) 1998 by the Board of Trustees
* of Leland Stanford Junior University.
* Copyright (C) 1998 Digital Equipment Corporation
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
#ifndef _WHEEL_H_
#define _WHEEL_H_
/* to manage the time wheel */
#include "protos.h"
#include "task.h"
/* WHEEL_SIZE must be a power of two */
#define WHEEL_SIZE 32768
#define WHEEL_MASK (WHEEL_SIZE-1)
/* use only the fields we need and pad the size until it is a power of 2 */
typedef struct wheel_ask {
struct task *next;
struct task *prev;
aint_time_t time;
int priority;
} wheel_task_t, *wheel_task_ptr;
extern wheel_task_ptr wheel;
extern wheel_task_ptr current_ptr;
extern wheel_task_ptr end_ptr;
extern aint_time_t start_time;
extern aint_time_t end_time;
extern task_ptr future_q;
extern void wheel_init ();
extern int wheel_empty ();
extern int task_cleanup ();
/* Define macros */
#define INLINE_TASK_EXTRACT(pnew) pnew = task_extract()
#define INLINE_TASK_INSERT(pnew) task_insert(pnew)
task_ptr task_pull_from_future ();
#ifdef __GNUC__
static inline
#else
# pragma inline(task_extract)
static
#endif
task_ptr
task_extract ()
{
task_ptr pnew;
/* search the time wheel first */
pnew = current_ptr->next;
if (pnew != (task_ptr) current_ptr) {
INLINE_REMOVE (pnew);
return pnew;
}
else {
task_ptr tptr, next;
while (1) {
/*
* Search the queues until we get to the end. Since we put a
* dummy item in the last (unused) queue, we don't need to
* check for overflow of the * current_ptr in each iteration
*/
do {
current_ptr++;
pnew = current_ptr->next;
} while (pnew == (task_ptr) current_ptr);
/* if we found a tsk, remove it and return */
if (current_ptr != end_ptr) {
INLINE_REMOVE (pnew);
return (pnew);
}
/* Wrap around processing */
current_ptr = &wheel[0];
end_time += WHEEL_SIZE;
start_time += WHEEL_SIZE;
pnew = future_q->next;
if (pnew == future_q)
return NULL;
for (; pnew != future_q; pnew = next) {
int diff = pnew->time - start_time;
next = pnew->next;
if (diff < WHEEL_SIZE) {
/* insert in priority order */
for (tptr = wheel[diff].prev;
tptr->priority < pnew->priority;
tptr = tptr->prev);
INLINE_REMOVE (pnew);
INLINE_INSERT_AFTER (tptr, pnew);
}
}
pnew = current_ptr->next;
if (pnew != (task_ptr) current_ptr) {
INLINE_REMOVE (pnew);
return pnew;
}
}
}
}
#ifdef __GNUC__
static inline
#else
#pragma inline(task_insert)
static
#endif
void
task_insert (task_ptr ptask)
{
int index;
task_ptr tptr;
/* printf("task_insert: time is %d\n", (int) ptask->time); */
index = ptask->time - start_time;
if (index < WHEEL_SIZE) {
/*
* insert in priority order
*/
for (tptr = wheel[index].prev;
tptr->priority < ptask->priority;
tptr = tptr->prev) {
/*
* Empty statement
*/
}
INLINE_INSERT_AFTER (tptr, ptask);
}
else {
INLINE_ENQUEUE (future_q, ptask);
}
}
#endif /* _WHEEL_H_ */