Previous 199869 Revisions Next

r32162 Thursday 18th September, 2014 at 00:51:41 UTC by Alex Jackson
diexec.c: Cache a pointer directly to the machine scheduler at startup,
to eliminate device().machine().scheduler() chains all over the place (nw)

This change has been sitting in my local tree for months, from when I was
(mostly unsuccessfully) working on c64 performance. It gives a small speedup
to drivers with many tightly-interleaved executing devices (i.e. Commodore
drivers) I didn't think it was worth making everyone do a clean build for
such tiny gains but I didn't have the heart to chuck it. Since I'm already
making another core-touching, clean-build-needed commit tonight, in it goes.
[src/emu]diexec.c diexec.h schedule.c

trunk/src/emu/schedule.c
r32161r32162
493493               exec->m_totalcycles += ran;
494494
495495               // update the local time for this CPU
496               attotime delta = attotime(0, exec->m_attoseconds_per_cycle * ran);
496               attotime delta(0, exec->m_attoseconds_per_cycle * ran);
497497               assert(delta >= attotime::zero);
498498               exec->m_localtime += delta;
499499               LOG(("         %d ran, %d total, time = %s\n", ran, (INT32)exec->m_totalcycles, exec->m_localtime.as_string(PRECISION)));
trunk/src/emu/diexec.c
r32161r32162
146146
147147bool device_execute_interface::executing() const
148148{
149   return (this == device().machine().scheduler().currently_executing());
149   return (this == m_scheduler->currently_executing());
150150}
151151
152152
r32161r32162
204204void device_execute_interface::abort_timeslice()
205205{
206206   // ignore if not the executing device
207   if (this != device().machine().scheduler().currently_executing())
207   if (!executing())
208208      return;
209209
210210   // swallow the remaining cycles
r32161r32162
225225void device_execute_interface::suspend_resume_changed()
226226{
227227   // inform the scheduler
228   device().machine().scheduler().suspend_resume_changed();
228   m_scheduler->suspend_resume_changed();
229229
230230   // if we're active, synchronize
231231   abort_timeslice();
r32161r32162
273273   suspend_until_trigger(TRIGGER_SUSPENDTIME + timetrig, true);
274274
275275   // then set a timer for it
276   device().machine().scheduler().timer_set(duration, FUNC(static_timed_trigger_callback), TRIGGER_SUSPENDTIME + timetrig, this);
276   m_scheduler->timer_set(duration, FUNC(static_timed_trigger_callback), TRIGGER_SUSPENDTIME + timetrig, this);
277277   timetrig = (timetrig + 1) % 256;
278278}
279279
r32161r32162
469469
470470void device_execute_interface::interface_pre_start()
471471{
472   m_scheduler = &device().machine().scheduler();
473
472474   // bind delegates
473475   m_vblank_interrupt.bind_relative_to(*device().owner());
474476   m_timed_interrupt.bind_relative_to(*device().owner());
r32161r32162
483485
484486   // allocate timers if we need them
485487   if (m_timed_interrupt_period != attotime::zero)
486      m_timedint_timer = device().machine().scheduler().timer_alloc(FUNC(static_trigger_periodic_interrupt), (void *)this);
488      m_timedint_timer = m_scheduler->timer_alloc(FUNC(static_trigger_periodic_interrupt), (void *)this);
487489}
488490
489491
r32161r32162
595597   m_divisor = attos;
596598
597599   // re-compute the perfect interleave factor
598   device().machine().scheduler().compute_perfect_interleave();
600   m_scheduler->compute_perfect_interleave();
599601}
600602
601603
r32161r32162
711713
712714device_execute_interface::device_input::device_input()
713715   : m_execute(NULL),
714      m_device(NULL),
715716      m_linenum(0),
716717      m_stored_vector(0),
717718      m_curvector(0),
r32161r32162
730731void device_execute_interface::device_input::start(device_execute_interface *execute, int linenum)
731732{
732733   m_execute = execute;
733   m_device = &m_execute->device();
734734   m_linenum = linenum;
735735
736736   reset();
737737
738   m_device->save_item(NAME(m_stored_vector), m_linenum);
739   m_device->save_item(NAME(m_curvector), m_linenum);
740   m_device->save_item(NAME(m_curstate), m_linenum);
738   device_t &device = m_execute->device();
739   device.save_item(NAME(m_stored_vector), m_linenum);
740   device.save_item(NAME(m_curvector), m_linenum);
741   device.save_item(NAME(m_curstate), m_linenum);
741742}
742743
743744
r32161r32162
759760
760761void device_execute_interface::device_input::set_state_synced(int state, int vector)
761762{
762   LOG(("set_state_synced('%s',%d,%d,%02x)\n", m_device->tag(), m_linenum, state, vector));
763   LOG(("set_state_synced('%s',%d,%d,%02x)\n", m_execute->device().tag(), m_linenum, state, vector));
763764
764if (TEMPLOG) printf("setline(%s,%d,%d,%d)\n", m_device->tag(), m_linenum, state, (vector == USE_STORED_VECTOR) ? 0 : vector);
765if (TEMPLOG) printf("setline(%s,%d,%d,%d)\n", m_execute->device().tag(), m_linenum, state, (vector == USE_STORED_VECTOR) ? 0 : vector);
765766   assert(state == ASSERT_LINE || state == HOLD_LINE || state == CLEAR_LINE || state == PULSE_LINE);
766767
767768   // treat PULSE_LINE as ASSERT+CLEAR
r32161r32162
769770   {
770771      // catch errors where people use PULSE_LINE for devices that don't support it
771772      if (m_linenum != INPUT_LINE_NMI && m_linenum != INPUT_LINE_RESET)
772         throw emu_fatalerror("device '%s': PULSE_LINE can only be used for NMI and RESET lines\n", m_device->tag());
773         throw emu_fatalerror("device '%s': PULSE_LINE can only be used for NMI and RESET lines\n", m_execute->device().tag());
773774
774775      set_state_synced(ASSERT_LINE, vector);
775776      set_state_synced(CLEAR_LINE, vector);
r32161r32162
783784      m_qindex--;
784785      empty_event_queue();
785786      event_index = m_qindex++;
786      logerror("Exceeded pending input line event queue on device '%s'!\n", m_device->tag());
787      logerror("Exceeded pending input line event queue on device '%s'!\n", m_execute->device().tag());
787788   }
788789
789790   // enqueue the event
r32161r32162
795796
796797      // if this is the first one, set the timer
797798      if (event_index == 0)
798         m_execute->device().machine().scheduler().synchronize(FUNC(static_empty_event_queue), 0, (void *)this);
799         m_execute->scheduler().synchronize(FUNC(static_empty_event_queue), 0, (void *)this);
799800   }
800801}
801802
r32161r32162
811812
812813void device_execute_interface::device_input::empty_event_queue()
813814{
814if (TEMPLOG) printf("empty_queue(%s,%d,%d)\n", m_device->tag(), m_linenum, m_qindex);
815if (TEMPLOG) printf("empty_queue(%s,%d,%d)\n", m_execute->device().tag(), m_linenum, m_qindex);
815816   // loop over all events
816817   for (int curevent = 0; curevent < m_qindex; curevent++)
817818   {
r32161r32162
834835         // if we're clearing the line that was previously asserted, reset the device
835836         else if (m_execute->suspended(SUSPEND_REASON_RESET))
836837         {
837            m_device->reset();
838            m_execute->device().reset();
838839            m_execute->resume(SUSPEND_REASON_RESET);
839840         }
840841      }
r32161r32162
867868               break;
868869
869870            default:
870               logerror("empty_event_queue device '%s', line %d, unknown state %d\n", m_device->tag(), m_linenum, m_curstate);
871               logerror("empty_event_queue device '%s', line %d, unknown state %d\n", m_execute->device().tag(), m_linenum, m_curstate);
871872               break;
872873         }
873874
r32161r32162
894895   // if the IRQ state is HOLD_LINE, clear it
895896   if (m_curstate == HOLD_LINE)
896897   {
897      LOG(("->set_irq_line('%s',%d,%d)\n", m_device->tag(), m_linenum, CLEAR_LINE));
898      LOG(("->set_irq_line('%s',%d,%d)\n", m_execute->device().tag(), m_linenum, CLEAR_LINE));
898899      m_execute->execute_set_input(m_linenum, CLEAR_LINE);
899900      m_curstate = CLEAR_LINE;
900901   }
trunk/src/emu/diexec.h
r32161r32162
113113
114114class emu_timer;
115115class screen_device;
116class device_scheduler;
116117
117118
118119// interrupt callback for VBLANK and timed interrupts
r32161r32162
154155   static void static_set_irq_acknowledge_callback(device_t &device, device_irq_acknowledge_delegate callback);
155156
156157   // execution management
158   device_scheduler &scheduler() const { assert(m_scheduler != NULL); return *m_scheduler; }
157159   bool executing() const;
158160   INT32 cycles_remaining() const;
159161   void eat_cycles(int cycles);
r32161r32162
239241      int default_irq_callback();
240242
241243      device_execute_interface *m_execute;// pointer to the execute interface
242      device_t *      m_device;           // pointer to our device
243244      int             m_linenum;          // which input line we are
244245
245246      INT32           m_stored_vector;    // most recently written vector
r32161r32162
253254      void empty_event_queue();
254255   };
255256
257   // scheduler
258   device_scheduler *      m_scheduler;                // pointer to the machine scheduler
259
256260   // configuration
257261   bool                    m_disabled;                 // disabled from executing?
258262   device_interrupt_delegate m_vblank_interrupt;       // for interrupts tied to VBLANK

Previous 199869 Revisions Next


© 1997-2024 The MAME Team