1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
22 #ifndef _SIM_EVENTS_C_
23 #define _SIM_EVENTS_C_
26 #include "sim-assert.h"
40 #include <signal.h> /* For SIGPROCMASK et.al. */
43 /* The ui_loop_hook is called to keep the GUI alive while the simulator
44 is running. The counter is to make sure we do not wake it too often.
47 extern void (*ui_loop_hook
) PARAMS ((int));
48 static unsigned int ui_loop_hook_counter
= 0;
54 /* core - target byte order */
59 /* core - big-endian */
64 /* core - little-endian */
70 /* sim - host byte order */
75 /* sim - big-endian */
80 /* sim - little-endian */
91 } sim_event_watchpoints
;
95 sim_event_watchpoints watching
;
97 sim_event_handler
*handler
;
99 signed64 time_of_event
;
100 /* watch wallclock event */
102 /* watch core address */
103 address_word core_addr
;
107 /* watch core/sim range */
108 int is_within
; /* 0/1 */
113 /* trace info (if any) */
120 /* The event queue maintains a single absolute time using two
123 TIME_OF_EVENT: this holds the time at which the next event is ment
124 to occure. If no next event it will hold the time of the last
127 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. A value
128 <= 0 (except when poll-event is being processed) indicates that
129 event processing is due. This variable is decremented once for
130 each iteration of a clock cycle.
132 Initially, the clock is started at time one (0) with TIME_OF_EVENT
133 == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
135 Clearly there is a bug in that this code assumes that the absolute
136 time counter will never become greater than 2^62.
138 To avoid the need to use 64bit arithmetic, the event queue always
139 contains at least one event scheduled every 16 000 ticks. This
140 limits the time from event counter to values less than
144 #if !defined (SIM_EVENTS_POLL_RATE)
145 #define SIM_EVENTS_POLL_RATE 0x1000
149 #define _ETRACE sd, NULL
152 #define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
155 #define ETRACE(ARGS) \
160 if (STRACE_DEBUG_P (sd)) \
163 SIM_FILTER_PATH (file, __FILE__); \
164 trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
172 /* event queue iterator - don't iterate over the held queue. */
174 #if EXTERN_SIM_EVENTS_P
176 next_event_queue (SIM_DESC sd
,
180 return &STATE_EVENTS (sd
)->queue
;
181 else if (queue
== &STATE_EVENTS (sd
)->queue
)
182 return &STATE_EVENTS (sd
)->watchpoints
;
183 else if (queue
== &STATE_EVENTS (sd
)->watchpoints
)
184 return &STATE_EVENTS (sd
)->watchedpoints
;
185 else if (queue
== &STATE_EVENTS (sd
)->watchedpoints
)
188 sim_io_error (sd
, "next_event_queue - bad queue");
194 STATIC_INLINE_SIM_EVENTS\
196 sim_events_poll (SIM_DESC sd
,
199 /* just re-schedule in 1000 million ticks time */
200 sim_events_schedule (sd
, SIM_EVENTS_POLL_RATE
, sim_events_poll
, sd
);
201 sim_io_poll_quit (sd
);
205 /* "events" module install handler.
206 This is called via sim_module_install to install the "events" subsystem
207 into the simulator. */
209 #if EXTERN_SIM_EVENTS_P
210 STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN
) sim_events_uninstall
;
211 STATIC_SIM_EVENTS (MODULE_INIT_FN
) sim_events_init
;
212 STATIC_SIM_EVENTS (MODULE_RESUME_FN
) sim_events_resume
;
213 STATIC_SIM_EVENTS (MODULE_SUSPEND_FN
) sim_events_suspend
;
216 #if EXTERN_SIM_EVENTS_P
218 sim_events_install (SIM_DESC sd
)
220 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
221 sim_module_add_uninstall_fn (sd
, sim_events_uninstall
);
222 sim_module_add_init_fn (sd
, sim_events_init
);
223 sim_module_add_resume_fn (sd
, sim_events_resume
);
224 sim_module_add_suspend_fn (sd
, sim_events_suspend
);
230 /* Suspend/resume the event queue manager when the simulator is not
233 #if EXTERN_SIM_EVENTS_P
235 sim_events_resume (SIM_DESC sd
)
237 sim_events
*events
= STATE_EVENTS (sd
);
238 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
239 SIM_ASSERT (events
->resume_wallclock
== 0);
240 events
->resume_wallclock
= sim_elapsed_time_get ();
245 #if EXTERN_SIM_EVENTS_P
247 sim_events_suspend (SIM_DESC sd
)
249 sim_events
*events
= STATE_EVENTS (sd
);
250 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
251 SIM_ASSERT (events
->resume_wallclock
!= 0);
252 events
->elapsed_wallclock
+= sim_elapsed_time_since (events
->resume_wallclock
);
253 events
->resume_wallclock
= 0;
259 /* Uninstall the "events" subsystem from the simulator. */
261 #if EXTERN_SIM_EVENTS_P
263 sim_events_uninstall (SIM_DESC sd
)
265 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
266 /* FIXME: free buffers, etc. */
273 #if EXTERN_SIM_EVENTS_P
275 sim_events_zalloc (SIM_DESC sd
)
277 sim_events
*events
= STATE_EVENTS (sd
);
278 sim_event
*new = events
->free_list
;
281 events
->free_list
= new->next
;
282 memset (new, 0, sizeof (*new));
286 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
290 sigfillset(&new_mask
);
291 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
293 new = ZALLOC (sim_event
);
294 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
296 sigprocmask (SIG_SETMASK
, &old_mask
, NULL
);
303 STATIC_INLINE_SIM_EVENTS\
305 sim_events_free (SIM_DESC sd
,
308 sim_events
*events
= STATE_EVENTS (sd
);
309 dead
->next
= events
->free_list
;
310 events
->free_list
= dead
;
311 if (dead
->trace
!= NULL
)
313 free (dead
->trace
); /* NB: asprintf returns a `free' buf */
319 /* Initialize the simulator event manager */
321 #if EXTERN_SIM_EVENTS_P
323 sim_events_init (SIM_DESC sd
)
325 sim_events
*events
= STATE_EVENTS (sd
);
327 /* drain the interrupt queue */
329 if (events
->held
== NULL
)
330 events
->held
= NZALLOC (sim_event
, MAX_NR_SIGNAL_SIM_EVENTS
);
332 /* drain the normal queues */
334 sim_event
**queue
= NULL
;
335 while ((queue
= next_event_queue (sd
, queue
)) != NULL
)
337 if (queue
== NULL
) break;
338 while (*queue
!= NULL
)
340 sim_event
*dead
= *queue
;
342 sim_events_free (sd
, dead
);
348 /* wind time back to zero */
349 events
->nr_ticks_to_process
= 1; /* start by doing queue */
350 events
->time_of_event
= 0;
351 events
->time_from_event
= 0;
352 events
->elapsed_wallclock
= 0;
353 events
->resume_wallclock
= 0;
355 /* schedule our initial counter event */
356 sim_events_schedule (sd
, 0, sim_events_poll
, sd
);
358 /* from now on, except when the large-int event is being processed
359 the event queue is non empty */
360 SIM_ASSERT (events
->queue
!= NULL
);
369 sim_events_time (SIM_DESC sd
)
371 sim_events
*events
= STATE_EVENTS (sd
);
372 return (events
->time_of_event
- events
->time_from_event
);
378 sim_events_elapsed_time (SIM_DESC sd
)
380 unsigned long elapsed
= STATE_EVENTS (sd
)->elapsed_wallclock
;
382 /* Are we being called inside sim_resume?
383 (Is there a simulation in progress?) */
384 if (STATE_EVENTS (sd
)->resume_wallclock
!= 0)
385 elapsed
+= sim_elapsed_time_since (STATE_EVENTS (sd
)->resume_wallclock
);
391 STATIC_INLINE_SIM_EVENTS\
393 update_time_from_event (SIM_DESC sd
)
395 sim_events
*events
= STATE_EVENTS (sd
);
396 signed64 current_time
= sim_events_time (sd
);
397 if (events
->queue
!= NULL
)
399 events
->time_of_event
= events
->queue
->time_of_event
;
400 events
->time_from_event
= (events
->queue
->time_of_event
- current_time
);
404 events
->time_of_event
= current_time
- 1;
405 events
->time_from_event
= -1;
407 SIM_ASSERT (current_time
== sim_events_time (sd
));
411 #if EXTERN_SIM_EVENTS_P
413 insert_sim_event (SIM_DESC sd
,
414 sim_event
*new_event
,
417 sim_events
*events
= STATE_EVENTS (sd
);
420 signed64 time_of_event
;
423 sim_io_error (sd
, "what is past is past!\n");
425 /* compute when the event should occure */
426 time_of_event
= sim_events_time (sd
) + delta
;
428 /* find the queue insertion point - things are time ordered */
429 prev
= &events
->queue
;
430 curr
= events
->queue
;
431 while (curr
!= NULL
&& time_of_event
>= curr
->time_of_event
)
433 SIM_ASSERT (curr
->next
== NULL
434 || curr
->time_of_event
<= curr
->next
->time_of_event
);
438 SIM_ASSERT (curr
== NULL
|| time_of_event
< curr
->time_of_event
);
441 new_event
->next
= curr
;
443 new_event
->time_of_event
= time_of_event
;
445 /* adjust the time until the first event */
446 update_time_from_event (sd
);
451 #if EXTERN_SIM_EVENTS_P
453 sim_events_schedule (SIM_DESC sd
,
455 sim_event_handler
*handler
,
459 return sim_events_schedule_vtracef (sd
, delta_time
, handler
, data
,
465 #if EXTERN_SIM_EVENTS_P
467 sim_events_schedule_tracef (SIM_DESC sd
,
469 sim_event_handler
*handler
,
474 sim_event
*new_event
;
477 new_event
= sim_events_schedule_vtracef (sd
, delta_time
, handler
, data
, fmt
, ap
);
484 #if EXTERN_SIM_EVENTS_P
486 sim_events_schedule_vtracef (SIM_DESC sd
,
488 sim_event_handler
*handler
,
493 sim_event
*new_event
= sim_events_zalloc (sd
);
494 new_event
->data
= data
;
495 new_event
->handler
= handler
;
496 new_event
->watching
= watch_timer
;
497 if (fmt
== NULL
|| !ETRACE_P
|| vasprintf (&new_event
->trace
, fmt
, ap
) < 0)
498 new_event
->trace
= NULL
;
499 insert_sim_event(sd
, new_event
, delta_time
);
501 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
502 (long)sim_events_time(sd
),
504 (long)new_event
->time_of_event
,
505 (long)new_event
->handler
,
506 (long)new_event
->data
,
507 (new_event
->trace
!= NULL
) ? ", " : "",
508 (new_event
->trace
!= NULL
) ? new_event
->trace
: ""));
514 #if EXTERN_SIM_EVENTS_P
516 sim_events_schedule_after_signal (SIM_DESC sd
,
518 sim_event_handler
*handler
,
521 sim_events
*events
= STATE_EVENTS (sd
);
522 sim_event
*new_event
;
523 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
527 sigfillset(&new_mask
);
528 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
531 /* allocate an event entry from the signal buffer */
532 new_event
= &events
->held
[events
->nr_held
];
534 if (events
->nr_held
> MAX_NR_SIGNAL_SIM_EVENTS
)
536 sim_engine_abort (NULL
, NULL
, NULL_CIA
,
537 "sim_events_schedule_after_signal - buffer oveflow");
540 new_event
->data
= data
;
541 new_event
->handler
= handler
;
542 new_event
->time_of_event
= delta_time
; /* work it out later */
543 new_event
->next
= NULL
;
545 events
->work_pending
= 1; /* notify main process */
547 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
549 sigprocmask (SIG_SETMASK
, &old_mask
, NULL
);
553 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
554 (long)sim_events_time(sd
),
556 (long)new_event
->time_of_event
,
557 (long)new_event
->handler
,
558 (long)new_event
->data
));
563 #if EXTERN_SIM_EVENTS_P
565 sim_events_watch_clock (SIM_DESC sd
,
566 unsigned delta_ms_time
,
567 sim_event_handler
*handler
,
570 sim_events
*events
= STATE_EVENTS (sd
);
571 sim_event
*new_event
= sim_events_zalloc (sd
);
573 new_event
->watching
= watch_clock
;
575 new_event
->data
= data
;
576 new_event
->handler
= handler
;
578 if (events
->resume_wallclock
== 0)
579 new_event
->wallclock
= (events
->elapsed_wallclock
+ delta_ms_time
);
581 new_event
->wallclock
= (events
->elapsed_wallclock
582 + sim_elapsed_time_since (events
->resume_wallclock
)
585 new_event
->next
= events
->watchpoints
;
586 events
->watchpoints
= new_event
;
587 events
->work_pending
= 1;
589 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
590 (long)sim_events_time (sd
),
592 (long)new_event
->wallclock
,
593 (long)new_event
->handler
,
594 (long)new_event
->data
));
600 #if EXTERN_SIM_EVENTS_P
602 sim_events_watch_sim (SIM_DESC sd
,
609 sim_event_handler
*handler
,
612 sim_events
*events
= STATE_EVENTS (sd
);
613 sim_event
*new_event
= sim_events_zalloc (sd
);
620 case 1: new_event
->watching
= watch_sim_host_1
; break;
621 case 2: new_event
->watching
= watch_sim_host_2
; break;
622 case 4: new_event
->watching
= watch_sim_host_4
; break;
623 case 8: new_event
->watching
= watch_sim_host_8
; break;
624 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
630 case 1: new_event
->watching
= watch_sim_be_1
; break;
631 case 2: new_event
->watching
= watch_sim_be_2
; break;
632 case 4: new_event
->watching
= watch_sim_be_4
; break;
633 case 8: new_event
->watching
= watch_sim_be_8
; break;
634 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
640 case 1: new_event
->watching
= watch_sim_le_1
; break;
641 case 2: new_event
->watching
= watch_sim_le_2
; break;
642 case 4: new_event
->watching
= watch_sim_le_4
; break;
643 case 8: new_event
->watching
= watch_sim_le_8
; break;
644 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
648 sim_io_error (sd
, "sim_events_watch_sim - invalid byte order");
651 new_event
->data
= data
;
652 new_event
->handler
= handler
;
654 new_event
->host_addr
= host_addr
;
656 new_event
->lb64
= lb
;
658 new_event
->ub64
= ub
;
659 new_event
->is_within
= (is_within
!= 0);
661 new_event
->next
= events
->watchpoints
;
662 events
->watchpoints
= new_event
;
663 events
->work_pending
= 1;
665 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
666 (long)sim_events_time (sd
),
668 (long)new_event
->host_addr
,
671 (long)new_event
->handler
,
672 (long)new_event
->data
));
678 #if EXTERN_SIM_EVENTS_P
680 sim_events_watch_core (SIM_DESC sd
,
681 address_word core_addr
,
688 sim_event_handler
*handler
,
691 sim_events
*events
= STATE_EVENTS (sd
);
692 sim_event
*new_event
= sim_events_zalloc (sd
);
699 case 1: new_event
->watching
= watch_core_targ_1
; break;
700 case 2: new_event
->watching
= watch_core_targ_2
; break;
701 case 4: new_event
->watching
= watch_core_targ_4
; break;
702 case 8: new_event
->watching
= watch_core_targ_8
; break;
703 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
709 case 1: new_event
->watching
= watch_core_be_1
; break;
710 case 2: new_event
->watching
= watch_core_be_2
; break;
711 case 4: new_event
->watching
= watch_core_be_4
; break;
712 case 8: new_event
->watching
= watch_core_be_8
; break;
713 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
719 case 1: new_event
->watching
= watch_core_le_1
; break;
720 case 2: new_event
->watching
= watch_core_le_2
; break;
721 case 4: new_event
->watching
= watch_core_le_4
; break;
722 case 8: new_event
->watching
= watch_core_le_8
; break;
723 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
727 sim_io_error (sd
, "sim_events_watch_core - invalid byte order");
730 new_event
->data
= data
;
731 new_event
->handler
= handler
;
733 new_event
->core_addr
= core_addr
;
734 new_event
->core_map
= core_map
;
736 new_event
->lb64
= lb
;
738 new_event
->ub64
= ub
;
739 new_event
->is_within
= (is_within
!= 0);
741 new_event
->next
= events
->watchpoints
;
742 events
->watchpoints
= new_event
;
743 events
->work_pending
= 1;
745 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
746 (long)sim_events_time (sd
),
748 (long)new_event
->host_addr
,
751 (long)new_event
->handler
,
752 (long)new_event
->data
));
758 #if EXTERN_SIM_EVENTS_P
760 sim_events_deschedule (SIM_DESC sd
,
761 sim_event
*event_to_remove
)
763 sim_events
*events
= STATE_EVENTS (sd
);
764 sim_event
*to_remove
= (sim_event
*)event_to_remove
;
765 if (event_to_remove
!= NULL
)
767 sim_event
**queue
= NULL
;
768 while ((queue
= next_event_queue (sd
, queue
)) != NULL
)
770 sim_event
**ptr_to_current
;
771 for (ptr_to_current
= queue
;
772 *ptr_to_current
!= NULL
&& *ptr_to_current
!= to_remove
;
773 ptr_to_current
= &(*ptr_to_current
)->next
);
774 if (*ptr_to_current
== to_remove
)
776 sim_event
*dead
= *ptr_to_current
;
777 *ptr_to_current
= dead
->next
;
779 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
780 (long) sim_events_time (sd
),
781 (long) event_to_remove
,
782 (long) dead
->time_of_event
,
783 (long) dead
->handler
,
785 (dead
->trace
!= NULL
) ? ", " : "",
786 (dead
->trace
!= NULL
) ? dead
->trace
: ""));
787 sim_events_free (sd
, dead
);
788 update_time_from_event (sd
);
789 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
795 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
796 (long) sim_events_time (sd
),
797 (long) event_to_remove
));
802 STATIC_INLINE_SIM_EVENTS\
804 sim_watch_valid (SIM_DESC sd
,
807 switch (to_do
->watching
)
810 #define WATCH_CORE(N,OP,EXT) \
812 unsigned_##N word = 0; \
813 int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
814 to_do->core_addr, sizeof (word)); \
816 ok = (nr_read == sizeof (unsigned_##N) \
817 && (to_do->is_within \
818 == (word >= to_do->lb##EXT \
819 && word <= to_do->ub##EXT)));
821 case watch_core_targ_1
:
823 WATCH_CORE (1, T2H
,);
826 case watch_core_targ_2
:
828 WATCH_CORE (2, T2H
,);
831 case watch_core_targ_4
:
833 WATCH_CORE (4, T2H
,);
836 case watch_core_targ_8
:
838 WATCH_CORE (8, T2H
,64);
842 case watch_core_be_1
:
844 WATCH_CORE (1, BE2H
,);
847 case watch_core_be_2
:
849 WATCH_CORE (2, BE2H
,);
852 case watch_core_be_4
:
854 WATCH_CORE (4, BE2H
,);
857 case watch_core_be_8
:
859 WATCH_CORE (8, BE2H
,64);
863 case watch_core_le_1
:
865 WATCH_CORE (1, LE2H
,);
868 case watch_core_le_2
:
870 WATCH_CORE (2, LE2H
,);
873 case watch_core_le_4
:
875 WATCH_CORE (4, LE2H
,);
878 case watch_core_le_8
:
880 WATCH_CORE (8, LE2H
,64);
885 #define WATCH_SIM(N,OP,EXT) \
887 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
889 ok = (to_do->is_within \
890 == (word >= to_do->lb##EXT \
891 && word <= to_do->ub##EXT));
893 case watch_sim_host_1
:
895 WATCH_SIM (1, word
= ,);
898 case watch_sim_host_2
:
900 WATCH_SIM (2, word
= ,);
903 case watch_sim_host_4
:
905 WATCH_SIM (4, word
= ,);
908 case watch_sim_host_8
:
910 WATCH_SIM (8, word
= ,64);
916 WATCH_SIM (1, BE2H
,);
921 WATCH_SIM (2, BE2H
,);
926 WATCH_SIM (4, BE2H
,);
931 WATCH_SIM (8, BE2H
,64);
937 WATCH_SIM (1, LE2H
,);
942 WATCH_SIM (1, LE2H
,);
947 WATCH_SIM (1, LE2H
,);
952 WATCH_SIM (1, LE2H
,64);
957 case watch_clock
: /* wallclock */
959 unsigned long elapsed_time
= sim_events_elapsed_time (sd
);
960 return (elapsed_time
>= to_do
->wallclock
);
964 sim_io_error (sd
, "sim_watch_valid - bad switch");
974 sim_events_tick (SIM_DESC sd
)
976 sim_events
*events
= STATE_EVENTS (sd
);
978 /* this should only be called after the previous ticks have been
981 /* Advance the time but *only* if there is nothing to process */
982 if (events
->work_pending
983 || events
->time_from_event
== 0)
985 events
->nr_ticks_to_process
+= 1;
990 events
->time_from_event
-= 1;
998 sim_events_tickn (SIM_DESC sd
,
1001 sim_events
*events
= STATE_EVENTS (sd
);
1004 /* this should only be called after the previous ticks have been
1007 /* Advance the time but *only* if there is nothing to process */
1008 if (events
->work_pending
|| events
->time_from_event
< n
)
1010 events
->nr_ticks_to_process
+= n
;
1015 events
->time_from_event
-= n
;
1023 sim_events_slip (SIM_DESC sd
,
1026 sim_events
*events
= STATE_EVENTS (sd
);
1027 SIM_ASSERT (slip
> 0);
1029 /* Flag a ready event with work_pending instead of number of ticks
1030 to process so that the time continues to be correct */
1031 if (events
->time_from_event
< slip
)
1033 events
->work_pending
= 1;
1035 events
->time_from_event
-= slip
;
1041 sim_events_preprocess (SIM_DESC sd
,
1042 int events_were_last
,
1043 int events_were_next
)
1045 sim_events
*events
= STATE_EVENTS(sd
);
1046 if (events_were_last
)
1048 /* Halted part way through event processing */
1049 ASSERT (events
->nr_ticks_to_process
!= 0);
1050 /* The external world can't tell if the event that stopped the
1051 simulator was the last event to process. */
1052 ASSERT (events_were_next
);
1053 sim_events_process (sd
);
1055 else if (events_were_next
)
1057 /* Halted by the last processor */
1058 if (sim_events_tick (sd
))
1059 sim_events_process (sd
);
1066 sim_events_process (SIM_DESC sd
)
1068 sim_events
*events
= STATE_EVENTS(sd
);
1069 signed64 event_time
= sim_events_time(sd
);
1071 /* Clear work_pending before checking nr_held. Clearing
1072 work_pending after nr_held (with out a lock could loose an
1074 events
->work_pending
= 0;
1076 /* move any events that were asynchronously queued by any signal
1077 handlers onto the real event queue. */
1078 if (events
->nr_held
> 0)
1082 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1086 sigfillset(&new_mask
);
1087 sigprocmask(SIG_SETMASK
, &new_mask
, &old_mask
);
1090 for (i
= 0; i
< events
->nr_held
; i
++)
1092 sim_event
*entry
= &events
->held
[i
];
1093 sim_events_schedule (sd
,
1094 entry
->time_of_event
,
1098 events
->nr_held
= 0;
1100 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1102 sigprocmask(SIG_SETMASK
, &old_mask
, NULL
);
1107 /* Process any watchpoints. Be careful to allow a watchpoint to
1108 appear/disappear under our feet.
1109 To ensure that watchpoints are processed only once per cycle,
1110 they are moved onto a watched queue, this returned to the
1111 watchpoint queue when all queue processing has been
1113 while (events
->watchpoints
!= NULL
)
1115 sim_event
*to_do
= events
->watchpoints
;
1116 events
->watchpoints
= to_do
->next
;
1117 if (sim_watch_valid (sd
, to_do
))
1119 sim_event_handler
*handler
= to_do
->handler
;
1120 void *data
= to_do
->data
;
1122 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1127 (to_do
->trace
!= NULL
) ? ", " : "",
1128 (to_do
->trace
!= NULL
) ? to_do
->trace
: ""));
1129 sim_events_free (sd
, to_do
);
1134 to_do
->next
= events
->watchedpoints
;
1135 events
->watchedpoints
= to_do
;
1139 /* consume all events for this or earlier times. Be careful to
1140 allow an event to appear/disappear under our feet */
1141 while (events
->queue
->time_of_event
<
1142 (event_time
+ events
->nr_ticks_to_process
))
1144 sim_event
*to_do
= events
->queue
;
1145 sim_event_handler
*handler
= to_do
->handler
;
1146 void *data
= to_do
->data
;
1147 events
->queue
= to_do
->next
;
1148 update_time_from_event (sd
);
1150 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1155 (to_do
->trace
!= NULL
) ? ", " : "",
1156 (to_do
->trace
!= NULL
) ? to_do
->trace
: ""));
1157 sim_events_free (sd
, to_do
);
1161 /* put things back where they belong ready for the next iteration */
1162 events
->watchpoints
= events
->watchedpoints
;
1163 events
->watchedpoints
= NULL
;
1164 if (events
->watchpoints
!= NULL
)
1165 events
->work_pending
= 1;
1167 /* advance the time */
1168 SIM_ASSERT (events
->time_from_event
>= events
->nr_ticks_to_process
);
1169 SIM_ASSERT (events
->queue
!= NULL
); /* always poll event */
1170 events
->time_from_event
-= events
->nr_ticks_to_process
;
1172 /* this round of processing complete */
1173 events
->nr_ticks_to_process
= 0;
1176 /* Now call the ui_loop_hook to give the gui a chance to
1179 if (ui_loop_hook
!= NULL
)
1181 /* attempt to limit calls to 1-10 per second */
1182 if (! (ui_loop_hook_counter
++ & 0xf))
1183 (*ui_loop_hook
) (-2); /* magic */