/* * Cancel the timer 'tp'. The timer object must have been initialized with * init_timer(3) first. If the timer was not set before, the call is a no-op. */ void cancel_timer(minix_timer_t * tp) { clock_t next_time, prev_time; int r, have_timers; if (!tmr_is_set(tp)) return; have_timers = tmrs_clrtimer(&timers, tp, &prev_time, &next_time); /* * If the earliest timer has been removed, we have to set the alarm to * the next timer, or cancel the alarm altogether if the last timer * has been canceled. */ if (!expiring) { if (!have_timers) r = sys_setalarm(0, FALSE /*abs_time*/); else if (prev_time != next_time) r = sys_setalarm(next_time, TRUE /*abs_time*/); else r = OK; if (r != OK) panic("cancel_timer: couldn't set alarm: %d", r); } }
/***************************************************************************** * _ddekit_timer_update * ****************************************************************************/ void _ddekit_timer_update() { lock_timer(); static myclock_t next_timout; if(list.next) { if(!_ddekit_timer_pending || list.next->exp < next_timout) { unsigned to = list.next->exp - jiffies; _ddekit_timer_pending = 1; if (list.next->exp <= jiffies) { DDEBUG_MSG_WARN("Timeout lies in past to %d, now: %d", list.next->exp, jiffies); to = 1; } sys_setalarm(to, 0 /* REL */); DDEBUG_MSG_VERBOSE("requesting alarm for clock tick %d , now %d", list.next->exp, jiffies); } next_timout = list.next->exp; } unlock_timer(); }
/*===========================================================================* * flt_alarm * *===========================================================================*/ clock_t flt_alarm(clock_t dt) { int r; if(dt < 0) return next_alarm; r = sys_setalarm(dt, 0); if(r != OK) panic("sys_setalarm failed: %d", r); if(dt == 0) { if(!next_alarm) panic("clearing unset alarm: %d", r); next_alarm = 0; } else { if(next_alarm) panic("overwriting alarm: %d", r); if ((r = getuptime(&next_alarm)) != OK) panic("getuptime failed: %d", r); next_alarm += dt; } return next_alarm; }
/*===========================================================================* * vbox_init * *===========================================================================*/ static int vbox_init(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the device. */ int devind; u16_t vid, did; struct VMMDevReportGuestInfo *req; int r; interval = DEFAULT_INTERVAL; drift = DEFAULT_DRIFT; if (env_argc > 1) optset_parse(optset_table, env_argv[1]); pci_init(); r = pci_first_dev(&devind, &vid, &did); for (;;) { if (r != 1) panic("backdoor device not found"); if (vid == VMMDEV_PCI_VID && did == VMMDEV_PCI_DID) break; r = pci_next_dev(&devind, &vid, &did); } pci_reserve(devind); port = pci_attr_r32(devind, PCI_BAR) & PCI_BAR_IO_MASK; irq = pci_attr_r8(devind, PCI_ILR); hook_id = 0; if ((r = sys_irqsetpolicy(irq, 0 /* IRQ_REENABLE */, &hook_id)) != OK) panic("unable to register IRQ: %d", r); if ((r = sys_irqenable(&hook_id)) != OK) panic("unable to enable IRQ: %d", r); if ((vir_ptr = alloc_contig(VMMDEV_BUF_SIZE, 0, &phys_ptr)) == NULL) panic("unable to allocate memory"); req = (struct VMMDevReportGuestInfo *) vir_ptr; req->add_version = VMMDEV_GUEST_VERSION; req->os_type = VMMDEV_GUEST_OS_OTHER; if ((r = vbox_request(&req->header, phys_ptr, VMMDEV_REQ_REPORTGUESTINFO, sizeof(*req))) != VMMDEV_ERR_OK) panic("backdoor device not functioning"); ticks = sys_hz() * interval; sys_setalarm(ticks, 0); return OK; }
/*===========================================================================* * init_scheduling * *===========================================================================*/ void init_scheduling(void) { int r; balance_timeout = BALANCE_TIMEOUT * sys_hz(); if ((r = sys_setalarm(balance_timeout, 0)) != OK) panic("sys_setalarm failed: %d", r); }
/*===========================================================================* * pm_expire_timers * *===========================================================================*/ PUBLIC void pm_expire_timers(clock_t now) { clock_t next_time; /* Check for expired timers and possibly reschedule an alarm. */ tmrs_exptimers(&pm_timers, now, &next_time); if (next_time > 0) { if (sys_setalarm(next_time, 1) != OK) panic(__FILE__, "PM expire timer couldn't set alarm.", NO_NUM); } }
/*===========================================================================* * pm_cancel_timer * *===========================================================================*/ PUBLIC void pm_cancel_timer(timer_t *tp) { clock_t next_time, prev_time; prev_time = tmrs_clrtimer(&pm_timers, tp, &next_time); /* If the earliest timer has been removed, we have to set the alarm to * the next timer, or cancel the alarm altogether if the last timer has * been cancelled (next_time will be 0 then). */ if (prev_time < next_time || ! next_time) { if (sys_setalarm(next_time, 1) != OK) panic(__FILE__, "PM expire timer couldn't set alarm.", NO_NUM); } }
/*===========================================================================* * cancel_timer * *===========================================================================*/ void cancel_timer(timer_t *tp) { clock_t next_time, prev_time; prev_time = tmrs_clrtimer(&timers, tp, &next_time); /* If the earliest timer has been removed, we have to set the alarm to * the next timer, or cancel the alarm altogether if the last timer * has been cancelled (next_time will be 0 then). */ if (expiring == 0 && (prev_time < next_time || ! next_time)) { if (sys_setalarm(next_time, 1) != OK) panic("cancel_timer: couldn't set alarm"); } }
/*===========================================================================* * init_server * *===========================================================================*/ PRIVATE void init_server(void) { /* Initialize the reincarnation server. */ struct sigaction sa; struct boot_image *ip; int s,t; /* Install signal handlers. Ask PM to transform signal into message. */ sa.sa_handler = SIG_MESS; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno); if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno); /* Initialize the system process table. Use the boot image from the kernel * and the device map from the FS to gather all needed information. */ if ((s = sys_getimage(image)) != OK) panic("RS","warning: couldn't get copy of image table", s); if ((s = getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap)) < 0) panic("RS","warning: couldn't get copy of dmap table", errno); /* Now initialize the table with the processes in the system image. * Prepend /sbin/ to the binaries so that we can actually find them. */ for (s=0; s< NR_BOOT_PROCS; s++) { ip = &image[s]; if (ip->proc_nr >= 0) { nr_in_use ++; rproc[s].r_flags = RS_IN_USE; rproc[s].r_proc_nr_e = ip->endpoint; rproc[s].r_pid = getnpid(ip->proc_nr); for(t=0; t< NR_DEVICES; t++) if (dmap[t].dmap_driver == ip->proc_nr) rproc[s].r_dev_nr = t; strcpy(rproc[s].r_cmd, "/sbin/"); strcpy(rproc[s].r_cmd+6, ip->proc_name); rproc[s].r_argc = 1; rproc[s].r_argv[0] = rproc[s].r_cmd; rproc[s].r_argv[1] = NULL; } } /* Set alarm to periodically check driver status. */ if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) panic("RS", "couldn't set alarm", s); }
/* This function in called every N ticks to rebalance the queues. The current * scheduler bumps processes down one priority when ever they run out of * quantum. This function will find all proccesses that have been bumped down, * and pulls them back up. This default policy will soon be changed. */ void balance_queues(void) { struct schedproc *rmp; int r, proc_nr; for (proc_nr=0, rmp=schedproc; proc_nr < NR_PROCS; proc_nr++, rmp++) { if (rmp->flags & IN_USE) { if (rmp->priority > rmp->max_priority) { rmp->priority -= 1; /* increase priority */ schedule_process_local(rmp); } } } if ((r = sys_setalarm(balance_timeout, 0)) != OK) panic("sys_setalarm failed: %d", r); }
/*===========================================================================* * sef_cb_init_restart * *===========================================================================*/ static int sef_cb_init_restart(int type, sef_init_info_t *info) { /* Restart the reincarnation server. */ int r; struct rproc *old_rs_rp, *new_rs_rp; assert(info->endpoint == RS_PROC_NR); /* Perform default state transfer first. */ r = SEF_CB_INIT_RESTART_STATEFUL(type, info); if(r != OK) { printf("SEF_CB_INIT_RESTART_STATEFUL failed: %d\n", r); return r; } /* New RS takes over. */ old_rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; new_rs_rp = rproc_ptr[_ENDPOINT_P(info->old_endpoint)]; if(rs_verbose) printf("RS: %s is the new RS after restart\n", srv_to_string(new_rs_rp)); /* If an update was in progress, end it. */ if(SRV_IS_UPDATING(old_rs_rp)) { end_update(ERESTART, RS_REPLY); } /* Update the service into the replica. */ r = update_service(&old_rs_rp, &new_rs_rp, RS_DONTSWAP, 0); if(r != OK) { printf("update_service failed: %d\n", r); return r; } /* Initialize the new RS instance. */ r = init_service(new_rs_rp, SEF_INIT_RESTART, 0); if(r != OK) { printf("init_service failed: %d\n", r); return r; } /* Reschedule a synchronous alarm for the next period. */ if (OK != (r=sys_setalarm(RS_DELTA_T, 0))) panic("couldn't set alarm: %d", r); return OK; }
/*===========================================================================* * expire_timers * *===========================================================================*/ void expire_timers(clock_t now) { clock_t next_time; /* Check for expired timers. Use a global variable to indicate that * watchdog functions are called, so that sys_setalarm() isn't called * more often than necessary when set_timer or cancel_timer are called * from these watchdog functions. */ expiring = 1; tmrs_exptimers(&timers, now, &next_time); expiring = 0; /* Reschedule an alarm if necessary. */ if (next_time > 0) { if (sys_setalarm(next_time, 1) != OK) panic("expire_timers: couldn't set alarm"); } }
/*===========================================================================* * set_timer * *===========================================================================*/ void set_timer(timer_t *tp, int ticks, tmr_func_t watchdog, int arg) { int r; clock_t now, prev_time = 0, next_time; if ((r = getuptime(&now)) != OK) panic("set_timer: couldn't get uptime"); /* Set timer argument and add timer to the list. */ tmr_arg(tp)->ta_int = arg; prev_time = tmrs_settimer(&timers, tp, now+ticks, watchdog, &next_time); /* Reschedule our synchronous alarm if necessary. */ if (expiring == 0 && (! prev_time || prev_time > next_time)) { if (sys_setalarm(next_time, 1) != OK) panic("set_timer: couldn't set alarm"); } }
/* * Set the timer 'tp' to trigger 'ticks' clock ticks in the future. When it * triggers, call function 'watchdog' with argument 'arg'. The given timer * object must have been initialized with init_timer(3) already. The given * number of ticks must be between 0 and TMRDIFF_MAX inclusive. A ticks value * of zero will cause the alarm to trigger on the next clock tick. If the * timer was already set, it will be canceled first. */ void set_timer(minix_timer_t *tp, clock_t ticks, tmr_func_t watchdog, int arg) { clock_t prev_time, next_time; int r, had_timers; if (ticks > TMRDIFF_MAX) panic("set_timer: ticks value too large: %u", (int)ticks); /* Add the timer to the list. */ had_timers = tmrs_settimer(&timers, tp, getticks() + ticks, watchdog, arg, &prev_time, &next_time); /* Reschedule our synchronous alarm if necessary. */ if (!expiring && (!had_timers || next_time != prev_time)) { if ((r = sys_setalarm(next_time, TRUE /*abs_time*/)) != OK) panic("set_timer: couldn't set alarm: %d", r); } }
/*===========================================================================* * pm_set_timer * *===========================================================================*/ PUBLIC void pm_set_timer(timer_t *tp, int ticks, tmr_func_t watchdog, int arg) { int r; clock_t now, prev_time = 0, next_time; if ((r = getuptime(&now)) != OK) panic(__FILE__, "PM couldn't get uptime", NO_NUM); /* Set timer argument and add timer to the list. */ tmr_arg(tp)->ta_int = arg; prev_time = tmrs_settimer(&pm_timers,tp,now+ticks,watchdog,&next_time); /* Reschedule our synchronous alarm if necessary. */ if (! prev_time || prev_time > next_time) { if (sys_setalarm(next_time, 1) != OK) panic(__FILE__, "PM set timer couldn't set alarm.", NO_NUM); } return; }
/* * Expire all timers that were set to expire before/at the given current time. */ void expire_timers(clock_t now) { clock_t next_time; int r, have_timers; /* * Check for expired timers. Use a global variable to indicate that * watchdog functions are called, so that sys_setalarm() isn't called * more often than necessary when set_timer or cancel_timer are called * from these watchdog functions. */ expiring = TRUE; have_timers = tmrs_exptimers(&timers, now, &next_time); expiring = FALSE; /* Reschedule an alarm if necessary. */ if (have_timers) { if ((r = sys_setalarm(next_time, TRUE /*abs_time*/)) != OK) panic("expire_timers: couldn't set alarm: %d", r); } }
/*===========================================================================* * vbox_update_time * *===========================================================================*/ static void vbox_update_time(void) { /* Update the current time if it has drifted too far. */ struct VMMDevReqHostTime *req; time_t otime, ntime; req = (struct VMMDevReqHostTime *) vir_ptr; if (vbox_request(&req->header, phys_ptr, VMMDEV_REQ_HOSTTIME, sizeof(*req)) == VMMDEV_ERR_OK) { time(&otime); /* old time */ ntime = (unsigned long)(req->time / 1000); /* new time */ /* Make time go forward, if the difference exceeds the drift * threshold. Never make time go backward. */ if ((int) (ntime - otime) >= drift) stime(&ntime); } sys_setalarm(ticks, 0); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the reincarnation server. */ struct sigaction sa; struct boot_image *ip; int s,i,j; int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs; struct rproc *rp; struct rprocpub *rpub; struct boot_image image[NR_BOOT_PROCS]; struct mproc mproc[NR_PROCS]; struct exec header; struct boot_image_priv *boot_image_priv; struct boot_image_sys *boot_image_sys; struct boot_image_dev *boot_image_dev; /* See if we run in verbose mode. */ env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); /* Initialize the global init descriptor. */ rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub, sizeof(rprocpub), CPF_READ); if(!GRANT_VALID(rinit.rproctab_gid)) { panic("RS", "unable to create rprocpub table grant", rinit.rproctab_gid); } /* Initialize the global update descriptor. */ rupdate.flags = 0; /* Get a copy of the boot image table. */ if ((s = sys_getimage(image)) != OK) { panic("RS", "unable to get copy of boot image table", s); } /* Determine the number of system services in the boot image table and * compute the size required for the boot image buffer. */ nr_image_srvs = 0; boot_image_buffer_size = 0; for(i=0;i<NR_BOOT_PROCS;i++) { ip = &image[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(ip->endpoint))) { continue; } nr_image_srvs++; /* Lookup the corresponding entry in the boot image sys table. */ boot_image_info_lookup(ip->endpoint, image, NULL, NULL, &boot_image_sys, NULL); /* If we must keep a copy of this system service, read the header * and increase the size of the boot image buffer. */ if(boot_image_sys->flags & SF_USE_COPY) { if((s = sys_getaoutheader(&header, i)) != OK) { panic("RS", "unable to get copy of a.out header", s); } boot_image_buffer_size += header.a_hdrlen + header.a_text + header.a_data; } } /* Determine the number of entries in the boot image priv table and make sure * it matches the number of system services in the boot image table. */ nr_image_priv_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } nr_image_priv_srvs++; } if(nr_image_srvs != nr_image_priv_srvs) { panic("RS", "boot image table and boot image priv table mismatch", NO_NUM); } /* Allocate boot image buffer. */ if(boot_image_buffer_size > 0) { boot_image_buffer = rs_startup_sbrk(boot_image_buffer_size); if(boot_image_buffer == (char *) -1) { panic("RS", "unable to allocate boot image buffer", NO_NUM); } } /* Reset the system process table. */ for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { rp->r_flags = 0; rp->r_pub = &rprocpub[rp - rproc]; rp->r_pub->in_use = FALSE; } /* Initialize the system process table in 4 steps, each of them following * the appearance of system services in the boot image priv table. * - Step 1: get a copy of the executable image of every system service that * requires it while it is not yet running. * In addition, set priviliges, sys properties, and dev properties (if any) * for every system service. */ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding entries in other tables. */ boot_image_info_lookup(boot_image_priv->endpoint, image, &ip, NULL, &boot_image_sys, &boot_image_dev); rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* * Get a copy of the executable image if required. */ rp->r_exec_len = 0; rp->r_exec = NULL; if(boot_image_sys->flags & SF_USE_COPY) { exec_image_copy(ip - image, ip, rp); } /* * Set privileges. */ /* Get label. */ strcpy(rpub->label, boot_image_priv->label); if(boot_image_priv->endpoint != RS_PROC_NR) { /* Force a static priv id for system services in the boot image. */ rp->r_priv.s_id = static_priv_id( _ENDPOINT_P(boot_image_priv->endpoint)); /* Initialize privilege bitmaps. */ rp->r_priv.s_flags = boot_image_priv->flags; /* priv flags */ rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */ memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to, sizeof(rp->r_priv.s_ipc_to)); /* targets */ /* Initialize kernel call mask bitmap from unordered set. */ fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS, rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE); /* Set the privilege structure. */ if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv))) != OK) { panic("RS", "unable to set privilege structure", s); } } /* Synch the privilege structure with the kernel. */ if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) { panic("RS", "unable to synch privilege structure", s); } /* * Set sys properties. */ rpub->sys_flags = boot_image_sys->flags; /* sys flags */ /* * Set dev properties. */ rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */ rpub->dev_style = boot_image_dev->dev_style; /* device style */ rpub->period = boot_image_dev->period; /* heartbeat period */ /* Get process name. */ strcpy(rpub->proc_name, ip->proc_name); /* Get command settings. */ rp->r_cmd[0]= '\0'; rp->r_argv[0] = rp->r_cmd; rp->r_argv[1] = NULL; rp->r_argc = 1; rp->r_script[0]= '\0'; /* Initialize vm call mask bitmap from unordered set. */ fill_call_mask(boot_image_priv->vm_calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE); /* Get some settings from the boot image table. */ rp->r_nice = ip->priority; rpub->endpoint = ip->endpoint; /* Set some defaults. */ rp->r_uid = 0; /* root */ rp->r_check_tm = 0; /* not checked yet */ getuptime(&rp->r_alive_tm); /* currently alive */ rp->r_stop_tm = 0; /* not exiting yet */ rp->r_restarts = 0; /* no restarts so far */ rp->r_set_resources = 0; /* don't set resources */ /* Mark as in use. */ rp->r_flags = RS_IN_USE; rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp; rpub->in_use = TRUE; } /* - Step 2: allow every system service in the boot image to run. */ nr_uncaught_init_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Ignore RS. */ if(boot_image_priv->endpoint == RS_PROC_NR) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* Allow the service to run. */ if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { panic("RS", "unable to initialize privileges", s); } /* Initialize service. We assume every service will always get * back to us here at boot time. */ if(boot_image_priv->flags & SYS_PROC) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { panic("RS", "unable to initialize service", s); } if(rpub->sys_flags & SF_SYNCH_BOOT) { /* Catch init ready message now to synchronize. */ catch_boot_init_ready(rpub->endpoint); } else { /* Catch init ready message later. */ nr_uncaught_init_srvs++; } } } /* - Step 3: let every system service complete initialization by * catching all the init ready messages left. */ while(nr_uncaught_init_srvs) { catch_boot_init_ready(ANY); nr_uncaught_init_srvs--; } /* - Step 4: all the system services in the boot image are now running. * Complete the initialization of the system process table in collaboration * with other system processes. */ if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) { panic("RS", "unable to get copy of PM process table", s); } for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* Get pid from PM process table. */ rp->r_pid = NO_PID; for (j = 0; j < NR_PROCS; j++) { if (mproc[j].mp_endpoint == rpub->endpoint) { rp->r_pid = mproc[j].mp_pid; break; } } if(j == NR_PROCS) { panic("RS", "unable to get pid", NO_NUM); } } /* * Now complete RS initialization process in collaboration with other * system services. */ /* Let the rest of the system know about our dynamically allocated buffer. */ if(boot_image_buffer_size > 0) { boot_image_buffer = rs_startup_sbrk_synch(boot_image_buffer_size); if(boot_image_buffer == (char *) -1) { panic("RS", "unable to synch boot image buffer", NO_NUM); } } /* Set alarm to periodically check service status. */ if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) panic("RS", "couldn't set alarm", s); /* Install signal handlers. Ask PM to transform signal into message. */ sa.sa_handler = SIG_MESS; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno); if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno); /* Initialize the exec pipe. */ if (pipe(exec_pipe) == -1) panic("RS", "pipe failed", errno); if (fcntl(exec_pipe[0], F_SETFD, fcntl(exec_pipe[0], F_GETFD) | FD_CLOEXEC) == -1) { panic("RS", "fcntl set FD_CLOEXEC on pipe input failed", errno); } if (fcntl(exec_pipe[1], F_SETFD, fcntl(exec_pipe[1], F_GETFD) | FD_CLOEXEC) == -1) { panic("RS", "fcntl set FD_CLOEXEC on pipe output failed", errno); } if (fcntl(exec_pipe[0], F_SETFL, fcntl(exec_pipe[0], F_GETFL) | O_NONBLOCK) == -1) { panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno); } /* Map out our own text and data. This is normally done in crtso.o * but RS is an exception - we don't get to talk to VM so early on. * That's why we override munmap() and munmap_text() in utility.c. * * _minix_unmapzero() is the same code in crtso.o that normally does * it on startup. It's best that it's there as crtso.o knows exactly * what the ranges are of the filler data. */ unmap_ok = 1; _minix_unmapzero(); return(OK); }
void sys_do_open_midi(int nmidiin, int *midiinvec, int nmidiout, int *midioutvec) { int i; for (i = 0; i < nmidiout; i++) oss_midioutfd[i] = -1; for (i = 0, oss_nmidiin = 0; i < nmidiin; i++) { int fd = -1, j, outdevindex = -1; char namebuf[80]; int devno = midiinvec[i] + oss_onebased; for (j = 0; j < nmidiout; j++) if (midioutvec[j] == midiinvec[i]) outdevindex = j; /* try to open the device for read/write. */ if (devno == 0 && fd < 0 && outdevindex >= 0) { sys_setalarm(1000000); fd = open("/dev/midi", O_RDWR | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device 1: tried /dev/midi READ/WRITE; returned %d\n", fd); if (outdevindex >= 0 && fd >= 0) oss_midioutfd[outdevindex] = fd; } if (fd < 0 && outdevindex >= 0) { sys_setalarm(1000000); sprintf(namebuf, "/dev/midi%2.2d", devno); fd = open(namebuf, O_RDWR | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device %d: tried %s READ/WRITE; returned %d\n", devno, namebuf, fd); if (outdevindex >= 0 && fd >= 0) oss_midioutfd[outdevindex] = fd; } if (fd < 0 && outdevindex >= 0) { sys_setalarm(1000000); sprintf(namebuf, "/dev/midi%d", devno); fd = open(namebuf, O_RDWR | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device %d: tried %s READ/WRITE; returned %d\n", devno, namebuf, fd); if (outdevindex >= 0 && fd >= 0) oss_midioutfd[outdevindex] = fd; } if (devno == 0 && fd < 0) { sys_setalarm(1000000); fd = open("/dev/midi", O_RDONLY | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device 1: tried /dev/midi READONLY; returned %d\n", fd); } if (fd < 0) { sys_setalarm(1000000); sprintf(namebuf, "/dev/midi%2.2d", devno); fd = open(namebuf, O_RDONLY | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device %d: tried %s READONLY; returned %d\n", devno, namebuf, fd); } if (fd < 0) { sys_setalarm(1000000); sprintf(namebuf, "/dev/midi%d", devno); fd = open(namebuf, O_RDONLY | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device %d: tried %s READONLY; returned %d\n", devno, namebuf, fd); } if (fd >= 0) oss_midiinfd[oss_nmidiin++] = fd; else post("couldn't open MIDI input device %d", devno); } for (i = 0, oss_nmidiout = 0; i < nmidiout; i++) { int fd = oss_midioutfd[i]; char namebuf[80]; int devno = midioutvec[i] + oss_onebased; if (devno == 0 && fd < 0) { sys_setalarm(1000000); fd = open("/dev/midi", O_WRONLY | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device 1: tried /dev/midi WRITEONLY; returned %d\n", fd); } if (fd < 0) { sys_setalarm(1000000); sprintf(namebuf, "/dev/midi%2.2d", devno); fd = open(namebuf, O_WRONLY | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device %d: tried %s WRITEONLY; returned %d\n", devno, namebuf, fd); } if (fd < 0) { sys_setalarm(1000000); sprintf(namebuf, "/dev/midi%d", devno); fd = open(namebuf, O_WRONLY | O_MIDIFLAG); if (sys_verbose) fprintf(stderr, "device %d: tried %s WRITEONLY; returned %d\n", devno, namebuf, fd); } if (fd >= 0) oss_midioutfd[oss_nmidiout++] = fd; else post("couldn't open MIDI output device %d", devno); } if (oss_nmidiin < nmidiin || oss_nmidiout < nmidiout || sys_verbose) post("opened %d MIDI input device(s) and %d MIDI output device(s).", oss_nmidiin, oss_nmidiout); sys_setalarm(0); }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the reincarnation server. */ struct boot_image *ip; int s,i; int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs; struct rproc *rp; struct rproc *replica_rp; struct rprocpub *rpub; struct boot_image image[NR_BOOT_PROCS]; struct boot_image_priv *boot_image_priv; struct boot_image_sys *boot_image_sys; struct boot_image_dev *boot_image_dev; int pid, replica_pid; endpoint_t replica_endpoint; int ipc_to; int *calls; int all_c[] = { ALL_C, NULL_C }; int no_c[] = { NULL_C }; /* See if we run in verbose mode. */ env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); if ((s = sys_getinfo(GET_HZ, &system_hz, sizeof(system_hz), 0, 0)) != OK) panic("Cannot get system timer frequency\n"); /* Initialize the global init descriptor. */ rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub, sizeof(rprocpub), CPF_READ); if(!GRANT_VALID(rinit.rproctab_gid)) { panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid); } /* Initialize some global variables. */ rupdate.flags = 0; shutting_down = FALSE; /* Get a copy of the boot image table. */ if ((s = sys_getimage(image)) != OK) { panic("unable to get copy of boot image table: %d", s); } /* Determine the number of system services in the boot image table. */ nr_image_srvs = 0; for(i=0;i<NR_BOOT_PROCS;i++) { ip = &image[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(ip->endpoint))) { continue; } nr_image_srvs++; } /* Determine the number of entries in the boot image priv table and make sure * it matches the number of system services in the boot image table. */ nr_image_priv_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } nr_image_priv_srvs++; } if(nr_image_srvs != nr_image_priv_srvs) { panic("boot image table and boot image priv table mismatch"); } /* Reset the system process table. */ for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { rp->r_flags = 0; rp->r_pub = &rprocpub[rp - rproc]; rp->r_pub->in_use = FALSE; } /* Initialize the system process table in 4 steps, each of them following * the appearance of system services in the boot image priv table. * - Step 1: set priviliges, sys properties, and dev properties (if any) * for every system service. */ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding entries in other tables. */ boot_image_info_lookup(boot_image_priv->endpoint, image, &ip, NULL, &boot_image_sys, &boot_image_dev); rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* * Set privileges. */ /* Get label. */ strcpy(rpub->label, boot_image_priv->label); /* Force a static priv id for system services in the boot image. */ rp->r_priv.s_id = static_priv_id( _ENDPOINT_P(boot_image_priv->endpoint)); /* Initialize privilege bitmaps and signal manager. */ rp->r_priv.s_flags = boot_image_priv->flags; /* priv flags */ rp->r_priv.s_trap_mask= SRV_OR_USR(rp, SRV_T, USR_T); /* traps */ ipc_to = SRV_OR_USR(rp, SRV_M, USR_M); /* targets */ fill_send_mask(&rp->r_priv.s_ipc_to, ipc_to == ALL_M); rp->r_priv.s_sig_mgr= SRV_OR_USR(rp, SRV_SM, USR_SM); /* sig mgr */ rp->r_priv.s_bak_sig_mgr = NONE; /* backup sig mgr */ /* Initialize kernel call mask bitmap. */ calls = SRV_OR_USR(rp, SRV_KC, USR_KC) == ALL_C ? all_c : no_c; fill_call_mask(calls, NR_SYS_CALLS, rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE); /* Set the privilege structure. */ if(boot_image_priv->endpoint != RS_PROC_NR) { if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv))) != OK) { panic("unable to set privilege structure: %d", s); } } /* Synch the privilege structure with the kernel. */ if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) { panic("unable to synch privilege structure: %d", s); } /* * Set sys properties. */ rpub->sys_flags = boot_image_sys->flags; /* sys flags */ /* * Set dev properties. */ rpub->dev_flags = boot_image_dev->flags; /* device flags */ rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */ rpub->dev_style = boot_image_dev->dev_style; /* device style */ rpub->dev_style2 = boot_image_dev->dev_style2; /* device style 2 */ /* Get process name. */ strcpy(rpub->proc_name, ip->proc_name); /* Build command settings. */ rp->r_cmd[0]= '\0'; rp->r_script[0]= '\0'; build_cmd_dep(rp); /* Initialize vm call mask bitmap. */ calls = SRV_OR_USR(rp, SRV_VC, USR_VC) == ALL_C ? all_c : no_c; fill_call_mask(calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE); /* Scheduling parameters. */ rp->r_scheduler = SRV_OR_USR(rp, SRV_SCH, USR_SCH); rp->r_priority = SRV_OR_USR(rp, SRV_Q, USR_Q); rp->r_quantum = SRV_OR_USR(rp, SRV_QT, USR_QT); /* Get some settings from the boot image table. */ rpub->endpoint = ip->endpoint; /* Set some defaults. */ rp->r_old_rp = NULL; /* no old version yet */ rp->r_new_rp = NULL; /* no new version yet */ rp->r_prev_rp = NULL; /* no prev replica yet */ rp->r_next_rp = NULL; /* no next replica yet */ rp->r_uid = 0; /* root */ rp->r_check_tm = 0; /* not checked yet */ getuptime(&rp->r_alive_tm); /* currently alive */ rp->r_stop_tm = 0; /* not exiting yet */ rp->r_restarts = 0; /* no restarts so far */ rp->r_period = 0; /* no period yet */ rp->r_exec = NULL; /* no in-memory copy yet */ rp->r_exec_len = 0; /* Mark as in use and active. */ rp->r_flags = RS_IN_USE | RS_ACTIVE; rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp; rpub->in_use = TRUE; } /* - Step 2: allow every system service in the boot image to run. */ nr_uncaught_init_srvs = 0; for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* RS is already running as we speak. */ if(boot_image_priv->endpoint == RS_PROC_NR) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { panic("unable to initialize RS: %d", s); } continue; } /* Allow the service to run. */ if ((s = sched_init_proc(rp)) != OK) { panic("unable to initialize scheduling: %d", s); } if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { panic("unable to initialize privileges: %d", s); } /* Initialize service. We assume every service will always get * back to us here at boot time. */ if(boot_image_priv->flags & SYS_PROC) { if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) { panic("unable to initialize service: %d", s); } if(rpub->sys_flags & SF_SYNCH_BOOT) { /* Catch init ready message now to synchronize. */ catch_boot_init_ready(rpub->endpoint); } else { /* Catch init ready message later. */ nr_uncaught_init_srvs++; } } } /* - Step 3: let every system service complete initialization by * catching all the init ready messages left. */ while(nr_uncaught_init_srvs) { catch_boot_init_ready(ANY); nr_uncaught_init_srvs--; } /* - Step 4: all the system services in the boot image are now running. * Complete the initialization of the system process table in collaboration * with other system services. */ for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; /* System services only. */ if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { continue; } /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; /* Get pid from PM. */ rp->r_pid = getnpid(rpub->endpoint); if(rp->r_pid == -1) { panic("unable to get pid"); } } /* Set alarm to periodically check service status. */ if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) panic("couldn't set alarm: %d", s); /* Now create a new RS instance with a private page table and let the current * instance live update into the replica. Clone RS' own slot first. */ rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; if((s = clone_slot(rp, &replica_rp)) != OK) { panic("unable to clone current RS instance: %d", s); } /* Fork a new RS instance. */ pid = srv_fork(); if(pid == -1) { panic("unable to fork a new RS instance"); } replica_pid = pid ? pid : getpid(); replica_endpoint = getnprocnr(replica_pid); replica_rp->r_pid = replica_pid; replica_rp->r_pub->endpoint = replica_endpoint; if(pid == 0) { /* New RS instance running. */ /* Live update the old instance into the new one. */ s = update_service(&rp, &replica_rp, RS_SWAP); if(s != OK) { panic("unable to live update RS: %d", s); } cpf_reload(); /* Clean up the old RS instance, the new instance will take over. */ cleanup_service(rp); /* Map out our own text and data. */ unmap_ok = 1; _minix_unmapzero(); /* Ask VM to pin memory for the new RS instance. */ if((s = vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN)) != OK) { panic("unable to pin memory for the new RS instance: %d", s); } } else { /* Old RS instance running. */ /* Set up privileges for the new instance and let it run. */ s = sys_privctl(replica_endpoint, SYS_PRIV_SET_SYS, &(replica_rp->r_priv)); if(s != OK) { panic("unable to set privileges for the new RS instance: %d", s); } if ((s = sched_init_proc(replica_rp)) != OK) { panic("unable to initialize RS replica scheduling: %d", s); } s = sys_privctl(replica_endpoint, SYS_PRIV_YIELD, NULL); if(s != OK) { panic("unable to yield control to the new RS instance: %d", s); } NOT_REACHABLE; } return(OK); }
void sys_alsa_do_open_midi(int nmidiin, int *midiinvec, int nmidiout, int *midioutvec) { char portname[50]; int err = 0; int client; int i; snd_seq_client_info_t *alsainfo; alsa_nmidiin = 0; alsa_nmidiout = 0; if (nmidiout == 0 && nmidiin == 0) return; if(nmidiin>MAXMIDIINDEV ) { post("midi input ports reduced to maximum %d", MAXMIDIINDEV); nmidiin=MAXMIDIINDEV; } if(nmidiout>MAXMIDIOUTDEV) { post("midi output ports reduced to maximum %d", MAXMIDIOUTDEV); nmidiout=MAXMIDIOUTDEV; } if (nmidiin>0 && nmidiout>0) err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_DUPLEX,0); else if (nmidiin > 0) err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0); else if (nmidiout > 0) err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_OUTPUT,0); if (err!=0) { sys_setalarm(1000000); post("couldn't open alsa sequencer"); return; } for (i=0;i<nmidiin;i++) { int port; sprintf(portname,"Pure Data Midi-In %d",i+1); port = snd_seq_create_simple_port(midi_handle,portname, SND_SEQ_PORT_CAP_WRITE |SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION); alsa_midiinfd[i] = port; if (port < 0) goto error; } for (i=0;i<nmidiout;i++) { int port; sprintf(portname,"Pure Data Midi-Out %d",i+1); port = snd_seq_create_simple_port(midi_handle,portname, SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION); alsa_midioutfd[i] = port; if (port < 0) goto error; } snd_seq_client_info_malloc(&alsainfo); snd_seq_get_client_info(midi_handle,alsainfo); snd_seq_client_info_set_name(alsainfo,"Pure Data"); client = snd_seq_client_info_get_client(alsainfo); snd_seq_set_client_info(midi_handle,alsainfo); snd_seq_client_info_free(alsainfo); post("Opened Alsa Client %d in:%d out:%d",client,nmidiin,nmidiout); sys_setalarm(0); snd_midi_event_new(ALSA_MAX_EVENT_SIZE,&midiev); alsa_nmidiout = nmidiout; alsa_nmidiin = nmidiin; return; error: sys_setalarm(1000000); post("couldn't open alsa MIDI output device"); return; }
void sys_do_open_midi(int nmidiin, int *midiinvec, int nmidiout, int *midioutvec) { int i; for (i = 0; i < nmidiout; i++) oss_midioutfd[i] = -1; for (i = 0, oss_nmidiin = 0; i < nmidiin; i++) { int fd = -1, j, outdevindex = -1; char namebuf[80]; int devno = midiinvec[i]; if (devno < 0 || devno >= oss_nmidiindevs) continue; for (j = 0; j < nmidiout; j++) if (midioutvec[j] >= 0 && midioutvec[j] <= oss_nmidioutdevs && !strcmp(oss_outdevnames[midioutvec[j]], oss_indevnames[devno])) outdevindex = j; sprintf(namebuf, "/dev/midi%s", oss_indevnames[devno]); /* try to open the device for read/write. */ if (outdevindex >= 0) { sys_setalarm(1000000); fd = open(namebuf, O_RDWR | O_MIDIFLAG); if (sys_verbose) post("tried to open %s read/write; got %d\n", namebuf, fd); if (outdevindex >= 0 && fd >= 0) oss_midioutfd[outdevindex] = fd; } /* OK, try read-only */ if (fd < 0) { sys_setalarm(1000000); fd = open(namebuf, O_RDONLY | O_MIDIFLAG); if (sys_verbose) post("tried to open %s read-only; got %d\n", namebuf, fd); } if (fd >= 0) oss_midiinfd[oss_nmidiin++] = fd; else post("couldn't open MIDI input device %s", namebuf); } for (i = 0, oss_nmidiout = 0; i < nmidiout; i++) { int fd = oss_midioutfd[i]; char namebuf[80]; int devno = midioutvec[i]; if (devno < 0 || devno >= oss_nmidioutdevs) continue; sprintf(namebuf, "/dev/midi%s", oss_outdevnames[devno]); if (fd < 0) { sys_setalarm(1000000); fd = open(namebuf, O_WRONLY | O_MIDIFLAG); if (sys_verbose) post("tried to open %s write-only; got %d\n", namebuf, fd); } if (fd >= 0) oss_midioutfd[oss_nmidiout++] = fd; else post("couldn't open MIDI output device %s", namebuf); } if (oss_nmidiin < nmidiin || oss_nmidiout < nmidiout || sys_verbose) post("opened %d MIDI input device(s) and %d MIDI output device(s).", oss_nmidiin, oss_nmidiout); sys_setalarm(0); }
/*===========================================================================* * w_intr_wait * *===========================================================================*/ static int intr_wait(int mask) { long v; #ifdef USE_INTR if (sys_irqenable(&hook_id) != OK) printf("Failed to enable irqenable irq\n"); /* Wait for a task completion interrupt. */ message m; int ipc_status; int ticks = SANE_TIMEOUT * sys_hz() / 1000000; if (ticks <= 0) ticks = 1; while (1) { int rr; sys_setalarm(ticks, 0); if ((rr = driver_receive(ANY, &m, &ipc_status)) != OK) { panic("driver_receive failed: %d", rr); }; if (is_ipc_notify(ipc_status)) { switch (_ENDPOINT_P(m.m_source)) { case CLOCK: /* Timeout. */ // w_timeout(); /* a.o. set w_status */ mmc_log_warn(&log, "TIMEOUT\n"); return 1; break; case HARDWARE: v = read32(base_address + MMCHS_SD_STAT); if (v & mask) { sys_setalarm(0, 0); return 0; } else if (v & (1 << 15)) { return 1; /* error */ } else { mmc_log_debug(&log, "unexpected HW interrupt 0x%08x mask 0X%08x\n", v, mask); if (sys_irqenable(&hook_id) != OK) printf ("Failed to re-enable irqenable irq\n"); continue; // return 1; } default: /* * unhandled message. queue it and * handle it in the blockdriver loop. */ blockdriver_mq_queue(&m, ipc_status); } } else { mmc_log_debug(&log, "Other\n"); /* * unhandled message. queue it and handle it in the * blockdriver loop. */ blockdriver_mq_queue(&m, ipc_status); } } sys_setalarm(0, 0); /* cancel the alarm */ #else spin_t spin; spin_init(&spin, SANE_TIMEOUT); /* Wait for completion */ int counter = 0; while (1 == 1) { counter++; v = read32(base_address + MMCHS_SD_STAT); if (spin_check(&spin) == FALSE) { mmc_log_warn(&log, "Timeout waiting for interrupt (%d) value 0x%08x mask 0x%08x\n", counter, v, mask); return 1; } if (v & mask) { return 0; } else if (v & 0xFF00) { mmc_log_debug(&log, "unexpected HW interrupt (%d) 0x%08x mask 0x%08x\n", v, mask); return 1; } } return 1; /* unreached */ #endif /* USE_INTR */ }