* gdbtk.tcl (files_command): Correctly insert list of files into
[deliverable/binutils-gdb.git] / sim / ppc / events.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef _EVENTS_C_
23 #define _EVENTS_C_
24
25 #ifndef STATIC_INLINE_EVENTS
26 #define STATIC_INLINE_EVENTS STATIC_INLINE
27 #endif
28
29
30 #include "basics.h"
31 #include "events.h"
32
33
34 /* The event queue maintains a single absolute time using two
35 variables.
36
37 TIME_OF_EVENT: this holds the time at which the next event is ment
38 to occure. If no next event it will hold the time of the last
39 event. The first event occures at time 0 - system start.
40
41 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
42 event is pending, this will be positive. If no future event is
43 pending this will be negative. This variable is decremented once
44 for each iteration of a clock cycle.
45
46 Clearly there is a bug in that this code assumes that the absolute
47 time counter will never become greater than 2^62. */
48
49 typedef struct _event_entry event_entry;
50 struct _event_entry {
51 void *data;
52 event_handler *handler;
53 signed64 time_of_event;
54 event_entry *next;
55 };
56
57 struct _event_queue {
58 event_entry *queue;
59 event_entry *volatile held;
60 event_entry *volatile *volatile held_end;
61 signed64 time_of_event;
62 signed64 time_from_event;
63 };
64
65
66 INLINE_EVENTS event_queue *
67 event_queue_create(void)
68 {
69 event_queue *new_event_queue = ZALLOC(event_queue);
70
71 new_event_queue->queue = NULL;
72 new_event_queue->held = NULL;
73 new_event_queue->held_end = &new_event_queue->held;
74 /* both times are already zero */
75 return new_event_queue;
76 }
77
78
79
80 STATIC_INLINE_EVENTS void
81 insert_event_entry(event_queue *events,
82 event_entry *new_event,
83 signed64 delta)
84 {
85 event_entry *curr;
86 event_entry **last;
87 signed64 time_of_event;
88
89 if (delta <= 0)
90 error("can not schedule event for current time\n");
91
92 /* compute when the event should occure */
93 time_of_event = (events->time_of_event
94 - events->time_from_event
95 + delta);
96
97 /* find the queue insertion point - things are time ordered */
98 last = &events->queue;
99 curr = events->queue;
100 while (curr != NULL && time_of_event >= curr->time_of_event) {
101 last = &curr->next;
102 curr = curr->next;
103 }
104
105 /* insert it */
106 new_event->next = curr;
107 *last = new_event;
108 new_event->time_of_event = time_of_event;
109
110 /* adjust the time until the first event */
111 events->time_from_event = (events->queue->time_of_event
112 - (events->time_of_event
113 - events->time_from_event));
114 events->time_of_event = events->queue->time_of_event;
115 }
116
117 INLINE_EVENTS event_entry_tag
118 event_queue_schedule(event_queue *events,
119 signed64 delta_time,
120 event_handler *handler,
121 void *data)
122 {
123 event_entry *new_event = ZALLOC(event_entry);
124 new_event->data = data;
125 new_event->handler = handler;
126 insert_event_entry(events, new_event, delta_time);
127 return new_event;
128 }
129
130
131 INLINE_EVENTS event_entry_tag
132 event_queue_schedule_after_signal(event_queue *events,
133 signed64 delta_time,
134 event_handler *handler,
135 void *data)
136 {
137 event_entry *new_event = ZALLOC(event_entry);
138
139 new_event->data = data;
140 new_event->handler = handler;
141 new_event->time_of_event = delta_time; /* work it out later */
142 new_event->next = NULL;
143
144 /*-LOCK-*/
145 if (events->held == NULL) {
146 events->held = new_event;
147 }
148 else {
149 *events->held_end = new_event;
150 }
151 events->held_end = &new_event->next;
152 /*-UNLOCK-*/
153
154 return new_event;
155 }
156
157
158 INLINE_EVENTS void
159 event_queue_deschedule(event_queue *events,
160 event_entry_tag event_to_remove)
161 {
162 if (event_to_remove != NULL) {
163 event_entry *current;
164 event_entry **ptr_to_current;
165 for (ptr_to_current = &events->queue, current = *ptr_to_current;
166 current != NULL && current != event_to_remove;
167 ptr_to_current = &current->next, current = *ptr_to_current);
168 if (current == event_to_remove) {
169 *ptr_to_current = current->next;
170 zfree(current);
171 /* Just forget to recompute the delay to the next event */
172 }
173 }
174 }
175
176
177
178
179 INLINE_EVENTS int
180 event_queue_tick(event_queue *events)
181 {
182 /* remove things from the asynchronous event queue onto the real one */
183 if (events->held != NULL) {
184 event_entry *held_events;
185 event_entry *curr_event;
186
187 /*-LOCK-*/
188 held_events = events->held;
189 events->held = NULL;
190 events->held_end = &events->held;
191 /*-UNLOCK-*/
192
193 do {
194 curr_event = held_events;
195 held_events = curr_event->next;
196 insert_event_entry(events, curr_event, curr_event->time_of_event);
197 } while (held_events != NULL);
198 }
199
200 /* advance time, checking to see if we've reached time zero which
201 would indicate the time for the next event has arrived */
202 events->time_from_event -= 1;
203 return events->time_from_event == 0;
204 }
205
206 INLINE_EVENTS void
207 event_queue_process(event_queue *events)
208 {
209 if (events->time_from_event == 0) {
210 /* consume all events for this or earlier times */
211 do {
212 event_entry *to_do = events->queue;
213 events->queue = to_do->next;
214 to_do->handler(events,
215 to_do->data);
216 zfree(to_do);
217 } while (events->queue != NULL
218 && events->queue->time_of_event <= events->time_of_event);
219 /* re-caculate time for new events */
220 if (events->queue != NULL) {
221 events->time_from_event = (events->queue->time_of_event
222 - events->time_of_event);
223 events->time_of_event = events->queue->time_of_event;
224 }
225 else {
226 /* nothing to do, time_from_event will go negative */
227 }
228 }
229 }
230
231 INLINE_EVENTS signed64
232 event_queue_time(event_queue *queue)
233 {
234 return queue->time_of_event - queue->time_from_event;
235 }
236
237
238 #endif /* _EVENTS_C_ */
This page took 0.03484 seconds and 4 git commands to generate.