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