sim: trace: centralize the system tracing
[deliverable/binutils-gdb.git] / sim / common / sim-events.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002-2015 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney and Red Hat.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22
23 #ifndef _SIM_EVENTS_C_
24 #define _SIM_EVENTS_C_
25
26 #include "sim-main.h"
27 #include "sim-assert.h"
28
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #else
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #endif
35 #endif
36
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40
41 #include <signal.h> /* For SIGPROCMASK et al. */
42
43 typedef enum {
44 watch_invalid,
45
46 /* core - target byte order */
47 watch_core_targ_1,
48 watch_core_targ_2,
49 watch_core_targ_4,
50 watch_core_targ_8,
51 /* core - big-endian */
52 watch_core_be_1,
53 watch_core_be_2,
54 watch_core_be_4,
55 watch_core_be_8,
56 /* core - little-endian */
57 watch_core_le_1,
58 watch_core_le_2,
59 watch_core_le_4,
60 watch_core_le_8,
61
62 /* sim - host byte order */
63 watch_sim_host_1,
64 watch_sim_host_2,
65 watch_sim_host_4,
66 watch_sim_host_8,
67 /* sim - big-endian */
68 watch_sim_be_1,
69 watch_sim_be_2,
70 watch_sim_be_4,
71 watch_sim_be_8,
72 /* sim - little-endian */
73 watch_sim_le_1,
74 watch_sim_le_2,
75 watch_sim_le_4,
76 watch_sim_le_8,
77
78 /* wallclock */
79 watch_clock,
80
81 /* timer */
82 watch_timer,
83 } sim_event_watchpoints;
84
85
86 struct _sim_event {
87 sim_event_watchpoints watching;
88 void *data;
89 sim_event_handler *handler;
90 /* timer event */
91 signed64 time_of_event;
92 /* watch wallclock event */
93 unsigned wallclock;
94 /* watch core address */
95 address_word core_addr;
96 unsigned core_map;
97 /* watch sim addr */
98 void *host_addr;
99 /* watch core/sim range */
100 int is_within; /* 0/1 */
101 unsigned ub;
102 unsigned lb;
103 unsigned64 ub64;
104 unsigned64 lb64;
105 /* trace info (if any) */
106 char *trace;
107 /* list */
108 sim_event *next;
109 };
110
111
112 /* The event queue maintains a single absolute time using two
113 variables.
114
115 TIME_OF_EVENT: this holds the time at which the next event is ment
116 to occur. If no next event it will hold the time of the last
117 event.
118
119 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. A value
120 <= 0 (except when poll-event is being processed) indicates that
121 event processing is due. This variable is decremented once for
122 each iteration of a clock cycle.
123
124 Initially, the clock is started at time one (0) with TIME_OF_EVENT
125 == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
126
127 Clearly there is a bug in that this code assumes that the absolute
128 time counter will never become greater than 2^62.
129
130 To avoid the need to use 64bit arithmetic, the event queue always
131 contains at least one event scheduled every 16 000 ticks. This
132 limits the time from event counter to values less than
133 16 000. */
134
135
136 #if !defined (SIM_EVENTS_POLL_RATE)
137 #define SIM_EVENTS_POLL_RATE 0x1000
138 #endif
139
140
141 #define _ETRACE sd, NULL
142
143 #undef ETRACE
144 #define ETRACE(ARGS) \
145 do \
146 { \
147 if (STRACE_EVENTS_P (sd)) \
148 { \
149 if (STRACE_DEBUG_P (sd)) \
150 { \
151 const char *file; \
152 SIM_FILTER_PATH (file, __FILE__); \
153 trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
154 } \
155 trace_printf ARGS; \
156 } \
157 } \
158 while (0)
159
160
161 /* event queue iterator - don't iterate over the held queue. */
162
163 #if EXTERN_SIM_EVENTS_P
164 static sim_event **
165 next_event_queue (SIM_DESC sd,
166 sim_event **queue)
167 {
168 if (queue == NULL)
169 return &STATE_EVENTS (sd)->queue;
170 else if (queue == &STATE_EVENTS (sd)->queue)
171 return &STATE_EVENTS (sd)->watchpoints;
172 else if (queue == &STATE_EVENTS (sd)->watchpoints)
173 return &STATE_EVENTS (sd)->watchedpoints;
174 else if (queue == &STATE_EVENTS (sd)->watchedpoints)
175 return NULL;
176 else
177 sim_io_error (sd, "next_event_queue - bad queue");
178 return NULL;
179 }
180 #endif
181
182
183 STATIC_INLINE_SIM_EVENTS\
184 (void)
185 sim_events_poll (SIM_DESC sd,
186 void *data)
187 {
188 /* just re-schedule in 1000 million ticks time */
189 sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
190 sim_io_poll_quit (sd);
191 }
192
193
194 /* "events" module install handler.
195 This is called via sim_module_install to install the "events" subsystem
196 into the simulator. */
197
198 #if EXTERN_SIM_EVENTS_P
199 STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
200 STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
201 STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
202 STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
203 #endif
204
205 #if EXTERN_SIM_EVENTS_P
206 SIM_RC
207 sim_events_install (SIM_DESC sd)
208 {
209 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
210 sim_module_add_uninstall_fn (sd, sim_events_uninstall);
211 sim_module_add_init_fn (sd, sim_events_init);
212 sim_module_add_resume_fn (sd, sim_events_resume);
213 sim_module_add_suspend_fn (sd, sim_events_suspend);
214 return SIM_RC_OK;
215 }
216 #endif
217
218
219 /* Suspend/resume the event queue manager when the simulator is not
220 running */
221
222 #if EXTERN_SIM_EVENTS_P
223 static SIM_RC
224 sim_events_resume (SIM_DESC sd)
225 {
226 sim_events *events = STATE_EVENTS (sd);
227 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
228 SIM_ASSERT (events->resume_wallclock == 0);
229 events->resume_wallclock = sim_elapsed_time_get ();
230 return SIM_RC_OK;
231 }
232 #endif
233
234 #if EXTERN_SIM_EVENTS_P
235 static SIM_RC
236 sim_events_suspend (SIM_DESC sd)
237 {
238 sim_events *events = STATE_EVENTS (sd);
239 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
240 SIM_ASSERT (events->resume_wallclock != 0);
241 events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
242 events->resume_wallclock = 0;
243 return SIM_RC_OK;
244 }
245 #endif
246
247
248 /* Uninstall the "events" subsystem from the simulator. */
249
250 #if EXTERN_SIM_EVENTS_P
251 static void
252 sim_events_uninstall (SIM_DESC sd)
253 {
254 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
255 /* FIXME: free buffers, etc. */
256 }
257 #endif
258
259
260 /* malloc/free */
261
262 #if EXTERN_SIM_EVENTS_P
263 static sim_event *
264 sim_events_zalloc (SIM_DESC sd)
265 {
266 sim_events *events = STATE_EVENTS (sd);
267 sim_event *new = events->free_list;
268 if (new != NULL)
269 {
270 events->free_list = new->next;
271 memset (new, 0, sizeof (*new));
272 }
273 else
274 {
275 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
276 /*-LOCK-*/
277 sigset_t old_mask;
278 sigset_t new_mask;
279 sigfillset (&new_mask);
280 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
281 #endif
282 new = ZALLOC (sim_event);
283 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
284 /*-UNLOCK-*/
285 sigprocmask (SIG_SETMASK, &old_mask, NULL);
286 #endif
287 }
288 return new;
289 }
290 #endif
291
292 STATIC_INLINE_SIM_EVENTS\
293 (void)
294 sim_events_free (SIM_DESC sd,
295 sim_event *dead)
296 {
297 sim_events *events = STATE_EVENTS (sd);
298 dead->next = events->free_list;
299 events->free_list = dead;
300 if (dead->trace != NULL)
301 {
302 free (dead->trace); /* NB: asprintf returns a `free' buf */
303 dead->trace = NULL;
304 }
305 }
306
307
308 /* Initialize the simulator event manager */
309
310 #if EXTERN_SIM_EVENTS_P
311 SIM_RC
312 sim_events_init (SIM_DESC sd)
313 {
314 sim_events *events = STATE_EVENTS (sd);
315
316 /* drain the interrupt queue */
317 events->nr_held = 0;
318 if (events->held == NULL)
319 events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
320
321 /* drain the normal queues */
322 {
323 sim_event **queue = NULL;
324 while ((queue = next_event_queue (sd, queue)) != NULL)
325 {
326 if (queue == NULL) break;
327 while (*queue != NULL)
328 {
329 sim_event *dead = *queue;
330 *queue = dead->next;
331 sim_events_free (sd, dead);
332 }
333 *queue = NULL;
334 }
335 }
336
337 /* wind time back to zero */
338 events->nr_ticks_to_process = 1; /* start by doing queue */
339 events->time_of_event = 0;
340 events->time_from_event = 0;
341 events->elapsed_wallclock = 0;
342 events->resume_wallclock = 0;
343
344 /* schedule our initial counter event */
345 sim_events_schedule (sd, 0, sim_events_poll, sd);
346
347 /* from now on, except when the large-int event is being processed
348 the event queue is non empty */
349 SIM_ASSERT (events->queue != NULL);
350
351 return SIM_RC_OK;
352 }
353 #endif
354
355
356 INLINE_SIM_EVENTS\
357 (signed64)
358 sim_events_time (SIM_DESC sd)
359 {
360 sim_events *events = STATE_EVENTS (sd);
361 return (events->time_of_event - events->time_from_event);
362 }
363
364
365 INLINE_SIM_EVENTS\
366 (unsigned long)
367 sim_events_elapsed_time (SIM_DESC sd)
368 {
369 unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
370
371 /* Are we being called inside sim_resume?
372 (Is there a simulation in progress?) */
373 if (STATE_EVENTS (sd)->resume_wallclock != 0)
374 elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
375
376 return elapsed;
377 }
378
379
380 /* Returns the time that remains before the event is raised. */
381 INLINE_SIM_EVENTS\
382 (signed64)
383 sim_events_remain_time (SIM_DESC sd, sim_event *event)
384 {
385 if (event == 0)
386 return 0;
387
388 return (event->time_of_event - sim_events_time (sd));
389 }
390
391
392
393 STATIC_INLINE_SIM_EVENTS\
394 (void)
395 update_time_from_event (SIM_DESC sd)
396 {
397 sim_events *events = STATE_EVENTS (sd);
398 signed64 current_time = sim_events_time (sd);
399 if (events->queue != NULL)
400 {
401 events->time_of_event = events->queue->time_of_event;
402 events->time_from_event = (events->queue->time_of_event - current_time);
403 }
404 else
405 {
406 events->time_of_event = current_time - 1;
407 events->time_from_event = -1;
408 }
409 if (STRACE_EVENTS_P (sd))
410 {
411 sim_event *event;
412 int i;
413 for (event = events->queue, i = 0;
414 event != NULL;
415 event = event->next, i++)
416 {
417 ETRACE ((_ETRACE,
418 "event time-from-event - time %ld, delta %ld - event %d, tag 0x%lx, time %ld, handler 0x%lx, data 0x%lx%s%s\n",
419 (long)current_time,
420 (long)events->time_from_event,
421 i,
422 (long)event,
423 (long)event->time_of_event,
424 (long)event->handler,
425 (long)event->data,
426 (event->trace != NULL) ? ", " : "",
427 (event->trace != NULL) ? event->trace : ""));
428 }
429 }
430 SIM_ASSERT (current_time == sim_events_time (sd));
431 }
432
433
434 #if EXTERN_SIM_EVENTS_P
435 static void
436 insert_sim_event (SIM_DESC sd,
437 sim_event *new_event,
438 signed64 delta)
439 {
440 sim_events *events = STATE_EVENTS (sd);
441 sim_event *curr;
442 sim_event **prev;
443 signed64 time_of_event;
444
445 if (delta < 0)
446 sim_io_error (sd, "what is past is past!\n");
447
448 /* compute when the event should occur */
449 time_of_event = sim_events_time (sd) + delta;
450
451 /* find the queue insertion point - things are time ordered */
452 prev = &events->queue;
453 curr = events->queue;
454 while (curr != NULL && time_of_event >= curr->time_of_event)
455 {
456 SIM_ASSERT (curr->next == NULL
457 || curr->time_of_event <= curr->next->time_of_event);
458 prev = &curr->next;
459 curr = curr->next;
460 }
461 SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
462
463 /* insert it */
464 new_event->next = curr;
465 *prev = new_event;
466 new_event->time_of_event = time_of_event;
467
468 /* adjust the time until the first event */
469 update_time_from_event (sd);
470 }
471 #endif
472
473
474 #if EXTERN_SIM_EVENTS_P
475 sim_event *
476 sim_events_schedule (SIM_DESC sd,
477 signed64 delta_time,
478 sim_event_handler *handler,
479 void *data)
480 {
481 va_list dummy;
482 memset (&dummy, 0, sizeof dummy);
483 return sim_events_schedule_vtracef (sd, delta_time, handler, data,
484 NULL, dummy);
485 }
486 #endif
487
488
489 #if EXTERN_SIM_EVENTS_P
490 sim_event *
491 sim_events_schedule_tracef (SIM_DESC sd,
492 signed64 delta_time,
493 sim_event_handler *handler,
494 void *data,
495 const char *fmt,
496 ...)
497 {
498 sim_event *new_event;
499 va_list ap;
500 va_start (ap, fmt);
501 new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
502 va_end (ap);
503 return new_event;
504 }
505 #endif
506
507
508 #if EXTERN_SIM_EVENTS_P
509 sim_event *
510 sim_events_schedule_vtracef (SIM_DESC sd,
511 signed64 delta_time,
512 sim_event_handler *handler,
513 void *data,
514 const char *fmt,
515 va_list ap)
516 {
517 sim_event *new_event = sim_events_zalloc (sd);
518 new_event->data = data;
519 new_event->handler = handler;
520 new_event->watching = watch_timer;
521 if (fmt == NULL || !STRACE_EVENTS_P (sd) || vasprintf (&new_event->trace, fmt, ap) < 0)
522 new_event->trace = NULL;
523 insert_sim_event (sd, new_event, delta_time);
524 ETRACE ((_ETRACE,
525 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
526 (long)sim_events_time (sd),
527 (long)new_event,
528 (long)new_event->time_of_event,
529 (long)new_event->handler,
530 (long)new_event->data,
531 (new_event->trace != NULL) ? ", " : "",
532 (new_event->trace != NULL) ? new_event->trace : ""));
533 return new_event;
534 }
535 #endif
536
537
538 #if EXTERN_SIM_EVENTS_P
539 void
540 sim_events_schedule_after_signal (SIM_DESC sd,
541 signed64 delta_time,
542 sim_event_handler *handler,
543 void *data)
544 {
545 sim_events *events = STATE_EVENTS (sd);
546 sim_event *new_event;
547 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
548 /*-LOCK-*/
549 sigset_t old_mask;
550 sigset_t new_mask;
551 sigfillset (&new_mask);
552 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
553 #endif
554
555 /* allocate an event entry from the signal buffer */
556 new_event = &events->held [events->nr_held];
557 events->nr_held ++;
558 if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
559 {
560 sim_engine_abort (NULL, NULL, NULL_CIA,
561 "sim_events_schedule_after_signal - buffer overflow");
562 }
563
564 new_event->data = data;
565 new_event->handler = handler;
566 new_event->time_of_event = delta_time; /* work it out later */
567 new_event->next = NULL;
568
569 events->work_pending = 1; /* notify main process */
570
571 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
572 /*-UNLOCK-*/
573 sigprocmask (SIG_SETMASK, &old_mask, NULL);
574 #endif
575
576 ETRACE ((_ETRACE,
577 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
578 (long)sim_events_time (sd),
579 (long)new_event,
580 (long)new_event->time_of_event,
581 (long)new_event->handler,
582 (long)new_event->data));
583 }
584 #endif
585
586
587 #if EXTERN_SIM_EVENTS_P
588 sim_event *
589 sim_events_watch_clock (SIM_DESC sd,
590 unsigned delta_ms_time,
591 sim_event_handler *handler,
592 void *data)
593 {
594 sim_events *events = STATE_EVENTS (sd);
595 sim_event *new_event = sim_events_zalloc (sd);
596 /* type */
597 new_event->watching = watch_clock;
598 /* handler */
599 new_event->data = data;
600 new_event->handler = handler;
601 /* data */
602 if (events->resume_wallclock == 0)
603 new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
604 else
605 new_event->wallclock = (events->elapsed_wallclock
606 + sim_elapsed_time_since (events->resume_wallclock)
607 + delta_ms_time);
608 /* insert */
609 new_event->next = events->watchpoints;
610 events->watchpoints = new_event;
611 events->work_pending = 1;
612 ETRACE ((_ETRACE,
613 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
614 (long)sim_events_time (sd),
615 (long)new_event,
616 (long)new_event->wallclock,
617 (long)new_event->handler,
618 (long)new_event->data));
619 return new_event;
620 }
621 #endif
622
623
624 #if EXTERN_SIM_EVENTS_P
625 sim_event *
626 sim_events_watch_sim (SIM_DESC sd,
627 void *host_addr,
628 int nr_bytes,
629 int byte_order,
630 int is_within,
631 unsigned64 lb,
632 unsigned64 ub,
633 sim_event_handler *handler,
634 void *data)
635 {
636 sim_events *events = STATE_EVENTS (sd);
637 sim_event *new_event = sim_events_zalloc (sd);
638 /* type */
639 switch (byte_order)
640 {
641 case 0:
642 switch (nr_bytes)
643 {
644 case 1: new_event->watching = watch_sim_host_1; break;
645 case 2: new_event->watching = watch_sim_host_2; break;
646 case 4: new_event->watching = watch_sim_host_4; break;
647 case 8: new_event->watching = watch_sim_host_8; break;
648 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
649 }
650 break;
651 case BIG_ENDIAN:
652 switch (nr_bytes)
653 {
654 case 1: new_event->watching = watch_sim_be_1; break;
655 case 2: new_event->watching = watch_sim_be_2; break;
656 case 4: new_event->watching = watch_sim_be_4; break;
657 case 8: new_event->watching = watch_sim_be_8; break;
658 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
659 }
660 break;
661 case LITTLE_ENDIAN:
662 switch (nr_bytes)
663 {
664 case 1: new_event->watching = watch_sim_le_1; break;
665 case 2: new_event->watching = watch_sim_le_2; break;
666 case 4: new_event->watching = watch_sim_le_4; break;
667 case 8: new_event->watching = watch_sim_le_8; break;
668 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
669 }
670 break;
671 default:
672 sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
673 }
674 /* handler */
675 new_event->data = data;
676 new_event->handler = handler;
677 /* data */
678 new_event->host_addr = host_addr;
679 new_event->lb = lb;
680 new_event->lb64 = lb;
681 new_event->ub = ub;
682 new_event->ub64 = ub;
683 new_event->is_within = (is_within != 0);
684 /* insert */
685 new_event->next = events->watchpoints;
686 events->watchpoints = new_event;
687 events->work_pending = 1;
688 ETRACE ((_ETRACE,
689 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
690 (long)sim_events_time (sd),
691 (long)new_event,
692 (long)new_event->host_addr,
693 (long)new_event->lb,
694 (long)new_event->ub,
695 (long)new_event->handler,
696 (long)new_event->data));
697 return new_event;
698 }
699 #endif
700
701
702 #if EXTERN_SIM_EVENTS_P
703 sim_event *
704 sim_events_watch_core (SIM_DESC sd,
705 address_word core_addr,
706 unsigned core_map,
707 int nr_bytes,
708 int byte_order,
709 int is_within,
710 unsigned64 lb,
711 unsigned64 ub,
712 sim_event_handler *handler,
713 void *data)
714 {
715 sim_events *events = STATE_EVENTS (sd);
716 sim_event *new_event = sim_events_zalloc (sd);
717 /* type */
718 switch (byte_order)
719 {
720 case 0:
721 switch (nr_bytes)
722 {
723 case 1: new_event->watching = watch_core_targ_1; break;
724 case 2: new_event->watching = watch_core_targ_2; break;
725 case 4: new_event->watching = watch_core_targ_4; break;
726 case 8: new_event->watching = watch_core_targ_8; break;
727 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
728 }
729 break;
730 case BIG_ENDIAN:
731 switch (nr_bytes)
732 {
733 case 1: new_event->watching = watch_core_be_1; break;
734 case 2: new_event->watching = watch_core_be_2; break;
735 case 4: new_event->watching = watch_core_be_4; break;
736 case 8: new_event->watching = watch_core_be_8; break;
737 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
738 }
739 break;
740 case LITTLE_ENDIAN:
741 switch (nr_bytes)
742 {
743 case 1: new_event->watching = watch_core_le_1; break;
744 case 2: new_event->watching = watch_core_le_2; break;
745 case 4: new_event->watching = watch_core_le_4; break;
746 case 8: new_event->watching = watch_core_le_8; break;
747 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
748 }
749 break;
750 default:
751 sim_io_error (sd, "sim_events_watch_core - invalid byte order");
752 }
753 /* handler */
754 new_event->data = data;
755 new_event->handler = handler;
756 /* data */
757 new_event->core_addr = core_addr;
758 new_event->core_map = core_map;
759 new_event->lb = lb;
760 new_event->lb64 = lb;
761 new_event->ub = ub;
762 new_event->ub64 = ub;
763 new_event->is_within = (is_within != 0);
764 /* insert */
765 new_event->next = events->watchpoints;
766 events->watchpoints = new_event;
767 events->work_pending = 1;
768 ETRACE ((_ETRACE,
769 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
770 (long)sim_events_time (sd),
771 (long)new_event,
772 (long)new_event->host_addr,
773 (long)new_event->lb,
774 (long)new_event->ub,
775 (long)new_event->handler,
776 (long)new_event->data));
777 return new_event;
778 }
779 #endif
780
781
782 #if EXTERN_SIM_EVENTS_P
783 void
784 sim_events_deschedule (SIM_DESC sd,
785 sim_event *event_to_remove)
786 {
787 sim_events *events = STATE_EVENTS (sd);
788 sim_event *to_remove = (sim_event*)event_to_remove;
789 if (event_to_remove != NULL)
790 {
791 sim_event **queue = NULL;
792 while ((queue = next_event_queue (sd, queue)) != NULL)
793 {
794 sim_event **ptr_to_current;
795 for (ptr_to_current = queue;
796 *ptr_to_current != NULL && *ptr_to_current != to_remove;
797 ptr_to_current = &(*ptr_to_current)->next);
798 if (*ptr_to_current == to_remove)
799 {
800 sim_event *dead = *ptr_to_current;
801 *ptr_to_current = dead->next;
802 ETRACE ((_ETRACE,
803 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
804 (long) sim_events_time (sd),
805 (long) event_to_remove,
806 (long) dead->time_of_event,
807 (long) dead->handler,
808 (long) dead->data,
809 (dead->trace != NULL) ? ", " : "",
810 (dead->trace != NULL) ? dead->trace : ""));
811 sim_events_free (sd, dead);
812 update_time_from_event (sd);
813 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
814 return;
815 }
816 }
817 }
818 ETRACE ((_ETRACE,
819 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
820 (long) sim_events_time (sd),
821 (long) event_to_remove));
822 }
823 #endif
824
825
826 STATIC_INLINE_SIM_EVENTS\
827 (int)
828 sim_watch_valid (SIM_DESC sd,
829 sim_event *to_do)
830 {
831 switch (to_do->watching)
832 {
833
834 #define WATCH_CORE(N,OP,EXT) \
835 int ok; \
836 unsigned_##N word = 0; \
837 int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
838 to_do->core_addr, sizeof (word)); \
839 OP (word); \
840 ok = (nr_read == sizeof (unsigned_##N) \
841 && (to_do->is_within \
842 == (word >= to_do->lb##EXT \
843 && word <= to_do->ub##EXT)));
844
845 case watch_core_targ_1:
846 {
847 WATCH_CORE (1, T2H,);
848 return ok;
849 }
850 case watch_core_targ_2:
851 {
852 WATCH_CORE (2, T2H,);
853 return ok;
854 }
855 case watch_core_targ_4:
856 {
857 WATCH_CORE (4, T2H,);
858 return ok;
859 }
860 case watch_core_targ_8:
861 {
862 WATCH_CORE (8, T2H,64);
863 return ok;
864 }
865
866 case watch_core_be_1:
867 {
868 WATCH_CORE (1, BE2H,);
869 return ok;
870 }
871 case watch_core_be_2:
872 {
873 WATCH_CORE (2, BE2H,);
874 return ok;
875 }
876 case watch_core_be_4:
877 {
878 WATCH_CORE (4, BE2H,);
879 return ok;
880 }
881 case watch_core_be_8:
882 {
883 WATCH_CORE (8, BE2H,64);
884 return ok;
885 }
886
887 case watch_core_le_1:
888 {
889 WATCH_CORE (1, LE2H,);
890 return ok;
891 }
892 case watch_core_le_2:
893 {
894 WATCH_CORE (2, LE2H,);
895 return ok;
896 }
897 case watch_core_le_4:
898 {
899 WATCH_CORE (4, LE2H,);
900 return ok;
901 }
902 case watch_core_le_8:
903 {
904 WATCH_CORE (8, LE2H,64);
905 return ok;
906 }
907 #undef WATCH_CORE
908
909 #define WATCH_SIM(N,OP,EXT) \
910 int ok; \
911 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
912 OP (word); \
913 ok = (to_do->is_within \
914 == (word >= to_do->lb##EXT \
915 && word <= to_do->ub##EXT));
916
917 case watch_sim_host_1:
918 {
919 WATCH_SIM (1, word = ,);
920 return ok;
921 }
922 case watch_sim_host_2:
923 {
924 WATCH_SIM (2, word = ,);
925 return ok;
926 }
927 case watch_sim_host_4:
928 {
929 WATCH_SIM (4, word = ,);
930 return ok;
931 }
932 case watch_sim_host_8:
933 {
934 WATCH_SIM (8, word = ,64);
935 return ok;
936 }
937
938 case watch_sim_be_1:
939 {
940 WATCH_SIM (1, BE2H,);
941 return ok;
942 }
943 case watch_sim_be_2:
944 {
945 WATCH_SIM (2, BE2H,);
946 return ok;
947 }
948 case watch_sim_be_4:
949 {
950 WATCH_SIM (4, BE2H,);
951 return ok;
952 }
953 case watch_sim_be_8:
954 {
955 WATCH_SIM (8, BE2H,64);
956 return ok;
957 }
958
959 case watch_sim_le_1:
960 {
961 WATCH_SIM (1, LE2H,);
962 return ok;
963 }
964 case watch_sim_le_2:
965 {
966 WATCH_SIM (1, LE2H,);
967 return ok;
968 }
969 case watch_sim_le_4:
970 {
971 WATCH_SIM (1, LE2H,);
972 return ok;
973 }
974 case watch_sim_le_8:
975 {
976 WATCH_SIM (1, LE2H,64);
977 return ok;
978 }
979 #undef WATCH_SIM
980
981 case watch_clock: /* wallclock */
982 {
983 unsigned long elapsed_time = sim_events_elapsed_time (sd);
984 return (elapsed_time >= to_do->wallclock);
985 }
986
987 default:
988 sim_io_error (sd, "sim_watch_valid - bad switch");
989 break;
990
991 }
992 return 1;
993 }
994
995
996 INLINE_SIM_EVENTS\
997 (int)
998 sim_events_tick (SIM_DESC sd)
999 {
1000 sim_events *events = STATE_EVENTS (sd);
1001
1002 /* this should only be called after the previous ticks have been
1003 fully processed */
1004
1005 /* Advance the time but *only* if there is nothing to process */
1006 if (events->work_pending
1007 || events->time_from_event == 0)
1008 {
1009 events->nr_ticks_to_process += 1;
1010 return 1;
1011 }
1012 else
1013 {
1014 events->time_from_event -= 1;
1015 return 0;
1016 }
1017 }
1018
1019
1020 INLINE_SIM_EVENTS\
1021 (int)
1022 sim_events_tickn (SIM_DESC sd,
1023 int n)
1024 {
1025 sim_events *events = STATE_EVENTS (sd);
1026 SIM_ASSERT (n > 0);
1027
1028 /* this should only be called after the previous ticks have been
1029 fully processed */
1030
1031 /* Advance the time but *only* if there is nothing to process */
1032 if (events->work_pending || events->time_from_event < n)
1033 {
1034 events->nr_ticks_to_process += n;
1035 return 1;
1036 }
1037 else
1038 {
1039 events->time_from_event -= n;
1040 return 0;
1041 }
1042 }
1043
1044
1045 INLINE_SIM_EVENTS\
1046 (void)
1047 sim_events_slip (SIM_DESC sd,
1048 int slip)
1049 {
1050 sim_events *events = STATE_EVENTS (sd);
1051 SIM_ASSERT (slip > 0);
1052
1053 /* Flag a ready event with work_pending instead of number of ticks
1054 to process so that the time continues to be correct */
1055 if (events->time_from_event < slip)
1056 {
1057 events->work_pending = 1;
1058 }
1059 events->time_from_event -= slip;
1060 }
1061
1062
1063 INLINE_SIM_EVENTS\
1064 (void)
1065 sim_events_preprocess (SIM_DESC sd,
1066 int events_were_last,
1067 int events_were_next)
1068 {
1069 sim_events *events = STATE_EVENTS (sd);
1070 if (events_were_last)
1071 {
1072 /* Halted part way through event processing */
1073 ASSERT (events->nr_ticks_to_process != 0);
1074 /* The external world can't tell if the event that stopped the
1075 simulator was the last event to process. */
1076 ASSERT (events_were_next);
1077 sim_events_process (sd);
1078 }
1079 else if (events_were_next)
1080 {
1081 /* Halted by the last processor */
1082 if (sim_events_tick (sd))
1083 sim_events_process (sd);
1084 }
1085 }
1086
1087
1088 INLINE_SIM_EVENTS\
1089 (void)
1090 sim_events_process (SIM_DESC sd)
1091 {
1092 sim_events *events = STATE_EVENTS (sd);
1093 signed64 event_time = sim_events_time (sd);
1094
1095 /* Clear work_pending before checking nr_held. Clearing
1096 work_pending after nr_held (with out a lock could loose an
1097 event). */
1098 events->work_pending = 0;
1099
1100 /* move any events that were asynchronously queued by any signal
1101 handlers onto the real event queue. */
1102 if (events->nr_held > 0)
1103 {
1104 int i;
1105
1106 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1107 /*-LOCK-*/
1108 sigset_t old_mask;
1109 sigset_t new_mask;
1110 sigfillset (&new_mask);
1111 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
1112 #endif
1113
1114 for (i = 0; i < events->nr_held; i++)
1115 {
1116 sim_event *entry = &events->held [i];
1117 sim_events_schedule (sd,
1118 entry->time_of_event,
1119 entry->handler,
1120 entry->data);
1121 }
1122 events->nr_held = 0;
1123
1124 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1125 /*-UNLOCK-*/
1126 sigprocmask (SIG_SETMASK, &old_mask, NULL);
1127 #endif
1128
1129 }
1130
1131 /* Process any watchpoints. Be careful to allow a watchpoint to
1132 appear/disappear under our feet.
1133 To ensure that watchpoints are processed only once per cycle,
1134 they are moved onto a watched queue, this returned to the
1135 watchpoint queue when all queue processing has been
1136 completed. */
1137 while (events->watchpoints != NULL)
1138 {
1139 sim_event *to_do = events->watchpoints;
1140 events->watchpoints = to_do->next;
1141 if (sim_watch_valid (sd, to_do))
1142 {
1143 sim_event_handler *handler = to_do->handler;
1144 void *data = to_do->data;
1145 ETRACE ((_ETRACE,
1146 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1147 (long) event_time,
1148 (long) to_do,
1149 (long) handler,
1150 (long) data,
1151 (to_do->trace != NULL) ? ", " : "",
1152 (to_do->trace != NULL) ? to_do->trace : ""));
1153 sim_events_free (sd, to_do);
1154 handler (sd, data);
1155 }
1156 else
1157 {
1158 to_do->next = events->watchedpoints;
1159 events->watchedpoints = to_do;
1160 }
1161 }
1162
1163 /* consume all events for this or earlier times. Be careful to
1164 allow an event to appear/disappear under our feet */
1165 while (events->queue->time_of_event <
1166 (event_time + events->nr_ticks_to_process))
1167 {
1168 sim_event *to_do = events->queue;
1169 sim_event_handler *handler = to_do->handler;
1170 void *data = to_do->data;
1171 events->queue = to_do->next;
1172 update_time_from_event (sd);
1173 ETRACE ((_ETRACE,
1174 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1175 (long) event_time,
1176 (long) to_do,
1177 (long) handler,
1178 (long) data,
1179 (to_do->trace != NULL) ? ", " : "",
1180 (to_do->trace != NULL) ? to_do->trace : ""));
1181 sim_events_free (sd, to_do);
1182 handler (sd, data);
1183 }
1184
1185 /* put things back where they belong ready for the next iteration */
1186 events->watchpoints = events->watchedpoints;
1187 events->watchedpoints = NULL;
1188 if (events->watchpoints != NULL)
1189 events->work_pending = 1;
1190
1191 /* advance the time */
1192 SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1193 SIM_ASSERT (events->queue != NULL); /* always poll event */
1194 events->time_from_event -= events->nr_ticks_to_process;
1195
1196 /* this round of processing complete */
1197 events->nr_ticks_to_process = 0;
1198 }
1199
1200 #endif
This page took 0.055698 seconds and 5 git commands to generate.