int probe_8259() { unsigned char om,cm,c2; unsigned int flags; if (p8259_probed < 0) return (int)p8259_probed; /* don't let the BIOS fiddle with the mask during the test. Fixes: Pentium machine where 1 out of 100 times programs fail with "cannot init PIC" */ flags = get_cpu_flags(); _cli(); om = p8259_read_mask(0); p8259_write_mask(0,0xFF); cm = p8259_read_mask(0); p8259_write_mask(0,0x00); c2 = p8259_read_mask(0); p8259_write_mask(0,om); set_cpu_flags(flags); if (cm != 0xFF || c2 != 0x00) return (p8259_probed=0); /* is a slave present too? */ flags = get_cpu_flags(); _cli(); om = p8259_read_mask(8); p8259_write_mask(8,0xFF); cm = p8259_read_mask(8); p8259_write_mask(8,0x00); c2 = p8259_read_mask(8); p8259_write_mask(8,om); set_cpu_flags(flags); if (cm == 0xFF && c2 == 0x00) p8259_slave_present = 1; return (p8259_probed=1); }
void scheduler() { unsigned int cpu_id = CPUID; struct scheduler_info *si = &(cpu[ cpu_id ].sched); struct thread *tr; int idle; int flip = 0; uint64_t requested_time = TIMESLICE; // We will never go back. set_cpu_flags( cpu_flags() & ~EFLAG_NESTED_TASK ); // Now we're working. acquire_spinlock( &(si->lock_scheduler) ); // Start timing the scheduler stats_time_start( &(cpu[ cpu_id ].st_schedulerTime) ); assert( (cpu_flags() & EFLAG_INTERRUPT) == 0 ); ack_apic(); while (1==1) { // Just show the world that we're still alive. ((char*)0xB8000)[158 - cpu_id * 2] ++ ; /// \todo remove one day // If the garbage collector has work to do, let it run. if ( gc_has_work( cpu_id ) == 0 ) { tr = smk_gc[ cpu_id ]; exec_thread( cpu_id, tr, TIMESLICE, 0 ); stats_time( cpu_id, &(cpu[ cpu_id ].st_systemTime) ); } // Find out when the next timed event is. requested_time = remove_timers( si, cpu[ cpu_id ].st_systemTime.usage ); idle = 0; // Fast queue support if ( flip == 0 ) { tr = get_fast( si ); if ( tr != NULL ) { exec_thread( cpu_id, tr, TIMESLICE, 0 ); stats_time( cpu_id, &(cpu[ cpu_id ].st_systemTime) ); // Maintain CPU time. if ( si->sched_count != 0 ) flip = 1; // Ensure others run continue; } } flip = 0; // Reset of fast queue // If there's nothing to do, do idle. if ( si->sched_count == 0 ) { if ( gc_has_work( cpu_id ) == 0 ) continue; // Al-e-oop! tr = smk_idle[ cpu_id ]; idle = 1; // Safe to wake up when required. } else { tr = si->sched_queue[ si->position ].tr; si->position = (si->position + 1) % si->sched_count; requested_time = TIMESLICE; idle = 0; // Don't interrupt until timeslice is over } // And run the selected thread. exec_thread( cpu_id, tr, requested_time, idle ); stats_time( cpu_id, &(cpu[ cpu_id ].st_systemTime) ); // Maintain CPU time. // // If the previous thread requested a state change, honour it. remove_last( si ); } }