/* Copyright 1995, 1997 J"orn Rennecke */ #include <signal.h> #include "common.h" #include "object.h" #include "comm.h" #define NEED_JOBTAB #include "schedule.h" int job_mask; int32 async_current_time, current_time; volatile int total_alarms, call_out_missing; static void flag_call_out(void); struct interactive **pending_link; typedef union { fd_set full; struct { long i[(MAX_USER+MAX_MISC_DESCRIPTORS-1)/8/sizeof(long)+1]; } small; } fd_uset; void schedule(void) { fd_uset readfds[2]; static const struct itimerval itv = { { TICK_SEC, TICK_USEC } , { TICK_SEC, TICK_USEC } }; static struct sigaction alarm_action = { (RETSIGTYPE(*)(int))flag_call_out, 0, SA_RESTART }; struct interactive *new_pending, *old_pending; sigaction(SIGALRM, &alarm_action, 0); setitimer(ITIMER_REAL, &itv, 0); bzero(&readfds, sizeof readfds); start_comm(&readfds[0].full); pending_link = &new_pending; for (;;) { struct timeval timeout; int npending; readfds[1].small = readfds[0].small; *pending_link = 0; timeout.tv_sec = !((p_int)new_pending|job_tab.mask); timeout.tv_usec = 0; npending = select(comm_nfds, &readfds[1].full, 0, 0, &timeout); old_pending = new_pending; pending_link = &new_pending; pending_commands(old_pending); if (npending <= 0) { if (npending && errno != EINTR) perror("select"); } else { /* * walk_fdset() will read new commands, execute max. one per * user, and append users with remaining commands to * pending_link. It also handles new connections and erq. */ walk_fdset(&readfds[1].full, npending); } job_tab.mask |= job_tab.isr_mask[0]; EXTRA_JOBS(); } } void flag_call_out(void) { call_out_missing += job_tab.isr_mask[0] | job_tab.isr_mask[1] >> JOB_check_call_out & 1; ISR_SET_JOBS(JOB(call_out)+JOB(check_call_out)); total_alarms++; } void check_call_out() { CLEAR_JOB(check_call_out); TRANSFER_ISR_JOBS; if (job_tab.mask & JOB(do_compact_mappings)) do_compact_mappings(); } void shutdown_simulation() { fatal("shutdown\n"); }