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