o Implement generic halt/restart/abort module.
[deliverable/binutils-gdb.git] / sim / common / sim-events.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, 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 _SIM_EVENTS_C_
23 #define _SIM_EVENTS_C_
24
25 #include "sim-main.h"
26 #include "sim-assert.h"
27
28 #include <signal.h>
29
30 typedef enum {
31 watch_invalid,
32
33 /* core - target byte order */
34 watch_core_targ_1,
35 watch_core_targ_2,
36 watch_core_targ_4,
37 watch_core_targ_8,
38 /* core - big-endian */
39 watch_core_be_1,
40 watch_core_be_2,
41 watch_core_be_4,
42 watch_core_be_8,
43 /* core - little-endian */
44 watch_core_le_1,
45 watch_core_le_2,
46 watch_core_le_4,
47 watch_core_le_8,
48
49 /* sim - host byte order */
50 watch_sim_host_1,
51 watch_sim_host_2,
52 watch_sim_host_4,
53 watch_sim_host_8,
54 /* sim - big-endian */
55 watch_sim_be_1,
56 watch_sim_be_2,
57 watch_sim_be_4,
58 watch_sim_be_8,
59 /* sim - little-endian */
60 watch_sim_le_1,
61 watch_sim_le_2,
62 watch_sim_le_4,
63 watch_sim_le_8,
64
65 /* wallclock */
66 watch_clock,
67
68 /* timer */
69 watch_timer,
70 } sim_watchpoints;
71
72
73 struct _sim_event {
74 sim_watchpoints watching;
75 void *data;
76 sim_event_handler *handler;
77 /* timer event */
78 signed64 time_of_event;
79 /* watch wallclock event */
80 unsigned wallclock;
81 /* watch core address */
82 address_word core_addr;
83 sim_core_maps core_map;
84 /* watch sim addr */
85 void *host_addr;
86 /* watch core/sim range */
87 unsigned ub;
88 unsigned lb;
89 unsigned64 ub64;
90 unsigned64 lb64;
91 /* list */
92 sim_event *next;
93 };
94
95
96 /* The event queue maintains a single absolute time using two
97 variables.
98
99 TIME_OF_EVENT: this holds the time at which the next event is ment
100 to occure. If no next event it will hold the time of the last
101 event.
102
103 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
104 event is pending, this will be positive. If no future event is
105 pending this will be negative. This variable is decremented once
106 for each iteration of a clock cycle.
107
108 Initially, the clock is started at time one (0) with TIME_OF_EVENT
109 == 0 and TIME_FROM_EVENT == 0.
110
111 Clearly there is a bug in that this code assumes that the absolute
112 time counter will never become greater than 2^62.
113
114 To avoid the need to use 64bit arithmetic, the event queue always
115 contains at least one event scheduled every 16 000 ticks. This
116 limits the time from event counter to values less than
117 16 000. */
118
119
120 #if !defined (SIM_EVENTS_POLL_RATE)
121 #define SIM_EVENTS_POLL_RATE 0x4000
122 #endif
123
124
125 #define _ETRACE sd
126
127 #undef ETRACE
128 #define ETRACE(ARGS) \
129 do \
130 { \
131 if (WITH_TRACE) \
132 { \
133 if (STATE_EVENTS (sd)->trace) \
134 { \
135 const char *file; \
136 SIM_FILTER_PATH (file, __FILE__); \
137 sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
138 sim_io_printf ARGS; \
139 } \
140 } \
141 } \
142 while (0)
143
144
145 /* event queue iterator */
146 STATIC_INLINE_SIM_EVENTS\
147 (sim_event **)
148 next_event_queue (SIM_DESC sd,
149 sim_event **queue)
150 {
151 if (queue == NULL)
152 return &STATE_EVENTS (sd)->queue;
153 else if (queue == &STATE_EVENTS (sd)->queue)
154 return &STATE_EVENTS (sd)->watchpoints;
155 else if (queue == &STATE_EVENTS (sd)->watchpoints)
156 return &STATE_EVENTS (sd)->watchedpoints;
157 else if (queue == &STATE_EVENTS (sd)->watchedpoints)
158 return NULL;
159 else
160 sim_io_error (sd, "next_event_queue - bad queue");
161 return NULL;
162 }
163
164
165 STATIC_INLINE_SIM_EVENTS\
166 (void)
167 sim_events_poll (SIM_DESC sd,
168 void *data)
169 {
170 /* just re-schedule in 1000 million ticks time */
171 sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
172 sim_io_poll_quit (sd);
173 }
174
175
176 /* "events" module install handler.
177 This is called via sim_module_install to install the "events" subsystem
178 into the simulator. */
179
180 EXTERN_SIM_EVENTS\
181 (SIM_RC)
182 sim_events_install (SIM_DESC sd)
183 {
184 sim_module_add_uninstall_fn (sd, sim_events_uninstall);
185 sim_module_add_init_fn (sd, sim_events_init);
186 return SIM_RC_OK;
187 }
188
189
190 /* Uninstall the "events" subsystem from the simulator. */
191
192 EXTERN_SIM_EVENTS\
193 (void)
194 sim_events_uninstall (SIM_DESC sd)
195 {
196 /* FIXME: free buffers, etc. */
197 }
198
199
200 /* Initialize the simulator event manager */
201
202 EXTERN_SIM_EVENTS\
203 (SIM_RC)
204 sim_events_init (SIM_DESC sd)
205 {
206 sim_events *events = STATE_EVENTS (sd);
207
208 /* drain the interrupt queue */
209 {
210 sim_event *event;
211 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
212 sigset_t old_mask;
213 sigset_t new_mask;
214 sigfillset(&new_mask);
215 /*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
216 #endif
217 event = events->held;
218 while (event != NULL) {
219 sim_event *dead = event;
220 event = event->next;
221 zfree(dead);
222 }
223 events->held = NULL;
224 events->held_end = &events->held;
225 events->work_pending = 0;
226 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
227 /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
228 #endif
229 }
230
231 /* drain the normal queues */
232 {
233 sim_event **queue = NULL;
234 while ((queue = next_event_queue (sd, queue)) != NULL)
235 {
236 if (queue == NULL) break;
237 while (*queue != NULL)
238 {
239 sim_event *dead = *queue;
240 *queue = dead->next;
241 zfree (dead);
242 }
243 *queue = NULL;
244 }
245 }
246
247 /* wind time back to zero */
248 events->processing = 1; /* start by doing queue */
249 events->time_of_event = 0;
250 events->time_from_event = 0;
251 events->initial_wallclock = sim_elapsed_time_get ();
252
253 /* schedule our initial counter event */
254 sim_events_schedule (sd, 0, sim_events_poll, sd);
255
256 /* from now on, except when the large-int event is being processed
257 the event queue is non empty */
258 SIM_ASSERT (events->queue != NULL);
259
260 return SIM_RC_OK;
261 }
262
263
264 INLINE_SIM_EVENTS\
265 (signed64)
266 sim_events_time (SIM_DESC sd)
267 {
268 sim_events *events = STATE_EVENTS (sd);
269 return events->time_of_event - events->time_from_event;
270 }
271
272
273 STATIC_INLINE_SIM_EVENTS\
274 (void)
275 update_time_from_event (SIM_DESC sd)
276 {
277 sim_events *events = STATE_EVENTS (sd);
278 signed64 current_time = sim_events_time (sd);
279 if (events->queue != NULL)
280 {
281 events->time_from_event = (events->queue->time_of_event - current_time);
282 events->time_of_event = events->queue->time_of_event;
283 }
284 else
285 {
286 events->time_of_event = current_time - 1;
287 events->time_from_event = -1;
288 }
289 SIM_ASSERT (current_time == sim_events_time (sd));
290 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
291 }
292
293
294 STATIC_INLINE_SIM_EVENTS\
295 (void)
296 insert_sim_event (SIM_DESC sd,
297 sim_event *new_event,
298 signed64 delta)
299 {
300 sim_events *events = STATE_EVENTS (sd);
301 sim_event *curr;
302 sim_event **prev;
303 signed64 time_of_event;
304
305 if (delta < 0)
306 sim_io_error (sd, "what is past is past!\n");
307
308 /* compute when the event should occure */
309 time_of_event = sim_events_time (sd) + delta;
310
311 /* find the queue insertion point - things are time ordered */
312 prev = &events->queue;
313 curr = events->queue;
314 while (curr != NULL && time_of_event >= curr->time_of_event)
315 {
316 SIM_ASSERT (curr->next == NULL
317 || curr->time_of_event <= curr->next->time_of_event);
318 prev = &curr->next;
319 curr = curr->next;
320 }
321 SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
322
323 /* insert it */
324 new_event->next = curr;
325 *prev = new_event;
326 new_event->time_of_event = time_of_event;
327
328 /* adjust the time until the first event */
329 update_time_from_event (sd);
330 }
331
332
333 EXTERN_SIM_EVENTS\
334 (sim_event *)
335 sim_events_schedule (SIM_DESC sd,
336 signed64 delta_time,
337 sim_event_handler *handler,
338 void *data)
339 {
340 sim_event *new_event = ZALLOC(sim_event);
341 new_event->data = data;
342 new_event->handler = handler;
343 new_event->watching = watch_timer;
344 insert_sim_event(sd, new_event, delta_time);
345 ETRACE((_ETRACE,
346 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
347 (long)sim_events_time(sd),
348 (long)new_event,
349 (long)new_event->time_of_event,
350 (long)new_event->handler,
351 (long)new_event->data));
352 return new_event;
353 }
354
355
356 EXTERN_SIM_EVENTS\
357 (sim_event *)
358 sim_events_schedule_after_signal(SIM_DESC sd,
359 signed64 delta_time,
360 sim_event_handler *handler,
361 void *data)
362 {
363 sim_events *events = STATE_EVENTS (sd);
364 sim_event *new_event = ZALLOC (sim_event);
365
366 new_event->data = data;
367 new_event->handler = handler;
368 new_event->time_of_event = delta_time; /* work it out later */
369 new_event->next = NULL;
370
371 {
372 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
373 /*-LOCK-*/
374 sigset_t old_mask;
375 sigset_t new_mask;
376 sigfillset(&new_mask);
377 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
378 #endif
379 if (events->held == NULL) {
380 events->held = new_event;
381 }
382 else {
383 *events->held_end = new_event;
384 }
385 events->held_end = &new_event->next;
386 events->work_pending = 1; /* notify main process */
387 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
388 /*-UNLOCK-*/
389 sigprocmask (SIG_SETMASK, &old_mask, NULL);
390 #endif
391 }
392
393 ETRACE ((_ETRACE,
394 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
395 (long)sim_events_time(sd),
396 (long)new_event,
397 (long)new_event->time_of_event,
398 (long)new_event->handler,
399 (long)new_event->data));
400
401 return new_event;
402 }
403
404
405 EXTERN_SIM_EVENTS\
406 (sim_event *)
407 sim_events_watch_clock (SIM_DESC sd,
408 unsigned wallclock_ms_time,
409 sim_event_handler *handler,
410 void *data)
411 {
412 sim_events *events = STATE_EVENTS (sd);
413 sim_event *new_event = ZALLOC (sim_event);
414 /* type */
415 new_event->watching = watch_clock;
416 /* handler */
417 new_event->data = data;
418 new_event->handler = handler;
419 /* data */
420 new_event->wallclock = wallclock_ms_time;
421 /* insert */
422 new_event->next = events->watchpoints;
423 events->watchpoints = new_event;
424 events->work_pending = 1;
425 ETRACE ((_ETRACE,
426 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
427 (long)sim_events_time (sd),
428 (long)new_event,
429 (long)new_event->wallclock,
430 (long)new_event->handler,
431 (long)new_event->data));
432 return new_event;
433 }
434
435
436 EXTERN_SIM_EVENTS\
437 (sim_event *)
438 sim_events_watch_sim (SIM_DESC sd,
439 void *host_addr,
440 int nr_bytes,
441 int byte_order,
442 unsigned64 lb,
443 unsigned64 ub,
444 sim_event_handler *handler,
445 void *data)
446 {
447 sim_events *events = STATE_EVENTS (sd);
448 sim_event *new_event = ZALLOC (sim_event);
449 /* type */
450 switch (byte_order)
451 {
452 case 0:
453 switch (nr_bytes)
454 {
455 case 1: new_event->watching = watch_sim_host_1; break;
456 case 2: new_event->watching = watch_sim_host_2; break;
457 case 4: new_event->watching = watch_sim_host_4; break;
458 case 8: new_event->watching = watch_sim_host_8; break;
459 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
460 }
461 break;
462 case BIG_ENDIAN:
463 switch (nr_bytes)
464 {
465 case 1: new_event->watching = watch_sim_be_1; break;
466 case 2: new_event->watching = watch_sim_be_2; break;
467 case 4: new_event->watching = watch_sim_be_4; break;
468 case 8: new_event->watching = watch_sim_be_8; break;
469 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
470 }
471 break;
472 case LITTLE_ENDIAN:
473 switch (nr_bytes)
474 {
475 case 1: new_event->watching = watch_sim_le_1; break;
476 case 2: new_event->watching = watch_sim_le_2; break;
477 case 4: new_event->watching = watch_sim_le_4; break;
478 case 8: new_event->watching = watch_sim_le_8; break;
479 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
480 }
481 break;
482 default:
483 sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
484 }
485 /* handler */
486 new_event->data = data;
487 new_event->handler = handler;
488 /* data */
489 new_event->host_addr = host_addr;
490 new_event->lb = lb;
491 new_event->lb64 = lb;
492 new_event->ub = ub;
493 new_event->ub64 = ub;
494 /* insert */
495 new_event->next = events->watchpoints;
496 events->watchpoints = new_event;
497 events->work_pending = 1;
498 ETRACE ((_ETRACE,
499 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
500 (long)sim_events_time (sd),
501 (long)new_event,
502 (long)new_event->host_addr,
503 (long)new_event->lb,
504 (long)new_event->ub,
505 (long)new_event->handler,
506 (long)new_event->data));
507 return new_event;
508 }
509
510
511 EXTERN_SIM_EVENTS\
512 (sim_event *)
513 sim_events_watch_core (SIM_DESC sd,
514 address_word core_addr,
515 sim_core_maps core_map,
516 int nr_bytes,
517 int byte_order,
518 unsigned64 lb,
519 unsigned64 ub,
520 sim_event_handler *handler,
521 void *data)
522 {
523 sim_events *events = STATE_EVENTS (sd);
524 sim_event *new_event = ZALLOC (sim_event);
525 /* type */
526 switch (byte_order)
527 {
528 case 0:
529 switch (nr_bytes)
530 {
531 case 1: new_event->watching = watch_core_targ_1; break;
532 case 2: new_event->watching = watch_core_targ_2; break;
533 case 4: new_event->watching = watch_core_targ_4; break;
534 case 8: new_event->watching = watch_core_targ_8; break;
535 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
536 }
537 break;
538 case BIG_ENDIAN:
539 switch (nr_bytes)
540 {
541 case 1: new_event->watching = watch_core_be_1; break;
542 case 2: new_event->watching = watch_core_be_2; break;
543 case 4: new_event->watching = watch_core_be_4; break;
544 case 8: new_event->watching = watch_core_be_8; break;
545 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
546 }
547 break;
548 case LITTLE_ENDIAN:
549 switch (nr_bytes)
550 {
551 case 1: new_event->watching = watch_core_le_1; break;
552 case 2: new_event->watching = watch_core_le_2; break;
553 case 4: new_event->watching = watch_core_le_4; break;
554 case 8: new_event->watching = watch_core_le_8; break;
555 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
556 }
557 break;
558 default:
559 sim_io_error (sd, "sim_events_watch_core - invalid byte order");
560 }
561 /* handler */
562 new_event->data = data;
563 new_event->handler = handler;
564 /* data */
565 new_event->core_addr = core_addr;
566 new_event->core_map = core_map;
567 new_event->lb = lb;
568 new_event->lb64 = lb;
569 new_event->ub = ub;
570 new_event->ub64 = ub;
571 /* insert */
572 new_event->next = events->watchpoints;
573 events->watchpoints = new_event;
574 events->work_pending = 1;
575 ETRACE ((_ETRACE,
576 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
577 (long)sim_events_time (sd),
578 (long)new_event,
579 (long)new_event->host_addr,
580 (long)new_event->lb,
581 (long)new_event->ub,
582 (long)new_event->handler,
583 (long)new_event->data));
584 return new_event;
585 }
586
587
588 EXTERN_SIM_EVENTS\
589 (void)
590 sim_events_deschedule (SIM_DESC sd,
591 sim_event *event_to_remove)
592 {
593 sim_events *events = STATE_EVENTS (sd);
594 sim_event *to_remove = (sim_event*)event_to_remove;
595 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
596 if (event_to_remove != NULL)
597 {
598 sim_event **queue = NULL;
599 while ((queue = next_event_queue (sd, queue)) != NULL)
600 {
601 sim_event **ptr_to_current;
602 for (ptr_to_current = queue;
603 *ptr_to_current != NULL && *ptr_to_current != to_remove;
604 ptr_to_current = &(*ptr_to_current)->next);
605 if (*ptr_to_current == to_remove)
606 {
607 sim_event *dead = *ptr_to_current;
608 *ptr_to_current = dead->next;
609 ETRACE ((_ETRACE,
610 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
611 (long) sim_events_time (sd),
612 (long) event_to_remove,
613 (long) dead->time_of_event,
614 (long) dead->handler,
615 (long) dead->data));
616 zfree (dead);
617 update_time_from_event (sd);
618 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
619 return;
620 }
621 }
622 }
623 ETRACE ((_ETRACE,
624 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
625 (long) sim_events_time (sd),
626 (long) event_to_remove));
627 }
628
629
630 STATIC_INLINE_SIM_EVENTS\
631 (int)
632 sim_watch_valid (SIM_DESC sd,
633 sim_event *to_do)
634 {
635 switch (to_do->watching)
636 {
637
638 #define WATCH_CORE(N,OP) \
639 { \
640 unsigned_##N word; \
641 sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
642 OP (word); \
643 return (word >= to_do->lb && word <= to_do->ub); \
644 }
645
646 case watch_core_targ_1: WATCH_CORE (1, T2H);
647 case watch_core_targ_2: WATCH_CORE (2, T2H);
648 case watch_core_targ_4: WATCH_CORE (4, T2H);
649 case watch_core_targ_8: WATCH_CORE (8, T2H);
650
651 case watch_core_be_1: WATCH_CORE (1, BE2H);
652 case watch_core_be_2: WATCH_CORE (2, BE2H);
653 case watch_core_be_4: WATCH_CORE (4, BE2H);
654 case watch_core_be_8: WATCH_CORE (8, BE2H);
655
656 case watch_core_le_1: WATCH_CORE (1, LE2H);
657 case watch_core_le_2: WATCH_CORE (2, LE2H);
658 case watch_core_le_4: WATCH_CORE (4, LE2H);
659 case watch_core_le_8: WATCH_CORE (8, LE2H);
660
661 #undef WATCH_CORE
662
663 #define WATCH_SIM(N,OP) \
664 { \
665 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
666 OP (word); \
667 return (word >= to_do->lb && word <= to_do->ub); \
668 }
669
670 case watch_sim_host_1: WATCH_SIM (1, word = );
671 case watch_sim_host_2: WATCH_SIM (2, word = );
672 case watch_sim_host_4: WATCH_SIM (4, word = );
673 case watch_sim_host_8: WATCH_SIM (8, word = );
674
675 case watch_sim_be_1: WATCH_SIM (1, BE2H);
676 case watch_sim_be_2: WATCH_SIM (2, BE2H);
677 case watch_sim_be_4: WATCH_SIM (4, BE2H);
678 case watch_sim_be_8: WATCH_SIM (8, BE2H);
679
680 case watch_sim_le_1: WATCH_SIM (1, LE2H);
681 case watch_sim_le_2: WATCH_SIM (1, LE2H);
682 case watch_sim_le_4: WATCH_SIM (1, LE2H);
683 case watch_sim_le_8: WATCH_SIM (1, LE2H);
684 #undef WATCH_SIM
685
686 case watch_clock: /* wallclock */
687 return (sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock)
688 < to_do->wallclock);
689
690 case watch_timer:
691 case watch_invalid:
692 sim_io_error (sd, "sim_watch_valid - bad switch");
693 break;
694
695 }
696 return 1;
697 }
698
699
700 INLINE_SIM_EVENTS\
701 (int)
702 sim_events_tick (SIM_DESC sd)
703 {
704 sim_events *events = STATE_EVENTS (sd);
705
706 /* this should only be called after the previous tick has been fully
707 processed */
708 SIM_ASSERT (!events->processing);
709
710 /* Advance the time but *only* if there is nothing to process */
711 if (events->work_pending
712 || events->time_from_event == 0)
713 {
714 events->processing = 1;
715 return 1;
716 }
717 else {
718 events->time_from_event -= 1;
719 return 0;
720 }
721 }
722
723
724 INLINE_SIM_EVENTS\
725 (void)
726 sim_events_preprocess (SIM_DESC sd,
727 int events_were_last,
728 int events_were_next)
729 {
730 sim_events *events = STATE_EVENTS(sd);
731 if (events->processing)
732 {
733 /* Halted midway through event processing */
734 ASSERT (events_were_last && events_were_next);
735 sim_events_process (sd);
736 }
737 else if (events_were_next)
738 {
739 /* Halted by the last processor */
740 ASSERT (!events->processing && !events_were_last);
741 if (sim_events_tick (sd))
742 sim_events_process (sd);
743 }
744 }
745
746
747 INLINE_SIM_EVENTS\
748 (void)
749 sim_events_process (SIM_DESC sd)
750 {
751 sim_events *events = STATE_EVENTS(sd);
752 signed64 event_time = sim_events_time(sd);
753
754 ASSERT (events->processing);
755
756 /* move any events that were queued by any signal handlers onto
757 the real event queue. */
758 if (events->held != NULL)
759 {
760 sim_event *held_events;
761 sim_event *curr_event;
762
763 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
764 /*-LOCK-*/
765 sigset_t old_mask;
766 sigset_t new_mask;
767 sigfillset(&new_mask);
768 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
769 #endif
770
771 held_events = events->held;
772 events->held = NULL;
773 events->held_end = &events->held;
774 events->work_pending = 0;
775
776 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
777 /*-UNLOCK-*/
778 sigprocmask(SIG_SETMASK, &old_mask, NULL);
779 #endif
780
781 do
782 {
783 curr_event = held_events;
784 held_events = curr_event->next;
785 insert_sim_event (sd, curr_event,
786 curr_event->time_of_event);
787 }
788 while (held_events != NULL);
789 }
790
791 /* Process any watchpoints. Be careful to allow a watchpoint to
792 appear/disappear under our feet.
793 To ensure that watchpoints are processed only once per cycle,
794 they are moved onto a watched queue, this returned to the
795 watchpoint queue when all queue processing has been
796 completed. */
797 while (events->watchpoints != NULL)
798 {
799 sim_event *to_do = events->watchpoints;
800 events->watchpoints = to_do->next;
801 if (sim_watch_valid (sd, to_do))
802 {
803 sim_event_handler *handler = to_do->handler;
804 void *data = to_do->data;
805 events->queue = to_do->next;
806 ETRACE((_ETRACE,
807 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
808 (long) event_time,
809 (long) to_do,
810 (long) handler,
811 (long) data));
812 zfree (to_do);
813 handler (sd, data);
814 }
815 else
816 {
817 to_do->next = events->watchedpoints;
818 events->watchedpoints = to_do;
819 }
820 }
821
822 /* consume all events for this or earlier times. Be careful to
823 allow an event to appear/disappear under our feet */
824 while (events->queue->time_of_event <= event_time)
825 {
826 sim_event *to_do = events->queue;
827 sim_event_handler *handler = to_do->handler;
828 void *data = to_do->data;
829 events->queue = to_do->next;
830 ETRACE((_ETRACE,
831 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
832 (long) event_time,
833 (long) to_do,
834 (long) handler,
835 (long) data));
836 zfree (to_do);
837 handler (sd, data);
838 }
839
840 /* put things back where they belong ready for the next iteration */
841 events->watchpoints = events->watchedpoints;
842 events->watchedpoints = NULL;
843 if (events->watchpoints != NULL)
844 events->work_pending = 1;
845
846 /* this round of processing complete */
847 events->processing = 0;
848
849 /* re-caculate time for new events - advance the time */
850 update_time_from_event(sd);
851 SIM_ASSERT(events->time_from_event > 0 && events->queue != NULL);
852 events->time_from_event -= 1;
853 }
854
855 #endif
This page took 0.0577 seconds and 4 git commands to generate.