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