*/
FORWARD _PROTOTYPE( void init_clock, (void) );
FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
-FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
+FORWARD _PROTOTYPE( void do_clocktick, (message *m_ptr) );
FORWARD _PROTOTYPE( void load_update, (void));
/* The CLOCK's timers queue. The functions in <timers.h> operate on this.
/* Go get a message. */
result = receive(ANY, &m);
+ if(result != OK)
+ panic("receive() failed", result);
+
/* Handle the request. Only clock ticks are expected. */
switch (m.m_type) {
case HARD_INT:
- result = do_clocktick(&m); /* handle clock tick */
+ do_clocktick(&m); /* handle clock tick */
break;
default: /* illegal request type */
kprintf("CLOCK: illegal request %d from %d.\n",
/*===========================================================================*
* do_clocktick *
*===========================================================================*/
-PRIVATE int do_clocktick(m_ptr)
+PRIVATE void do_clocktick(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Despite its name, this routine is not called on every clock tick. It
* place in the queues. As a side-effect a new process will be scheduled.
*/
if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
- if(prev_ptr->p_rts_flags == 0) /* if it was runnable .. */
- lock_dequeue(prev_ptr); /* take it off the queues */
- lock_enqueue(prev_ptr); /* and reinsert it again */
+ if(prev_ptr->p_rts_flags == 0) { /* if it was runnable .. */
+ lock_dequeue(prev_ptr); /* take it off the queues */
+ lock_enqueue(prev_ptr); /* and reinsert it again */
+ }
}
/* Check if a clock timer expired and run its watchdog function. */
TMR_NEVER : clock_timers->tmr_exp_time;
}
- /* Inhibit sending a reply. */
- return(EDONTREPLY);
+ return;
}
/*===========================================================================*
}
/* Set ready. The HARDWARE task is never ready. */
- if (rp->p_nr != HARDWARE) {
- rp->p_rts_flags = 0; /* runnable if no flags */
- lock_enqueue(rp); /* add to scheduling queues */
- } else {
- rp->p_rts_flags = NO_PRIORITY; /* prevent from running */
- }
+ if (rp->p_nr == HARDWARE) RTS_LOCK_SET(rp, NO_PRIORITY);
+ RTS_LOCK_UNSET(rp, SLOT_FREE); /* remove SLOT_FREE and schedule */
/* Code and data segments must be allocated in protected mode. */
alloc_segments(rp);
vir_clicks vlo, vhi; /* virtual clicks containing message to send */
#if 1
- if (caller_ptr->p_rts_flags & SLOT_FREE)
+ if (RTS_ISSET(caller_ptr, SLOT_FREE))
{
kprintf("called by the dead?!?\n");
return EINVAL;
/* Check whether the last process in the chain has a dependency. If it
* has not, the cycle cannot be closed and we are done.
*/
- if (xp->p_rts_flags & RECEIVING) { /* xp has dependency */
+ if (RTS_ISSET(xp, RECEIVING)) { /* xp has dependency */
if(xp->p_getfrom_e == ANY) src_dst = ANY;
else okendpt(xp->p_getfrom_e, &src_dst);
- } else if (xp->p_rts_flags & SENDING) { /* xp has dependency */
+ } else if (RTS_ISSET(xp, SENDING)) { /* xp has dependency */
okendpt(xp->p_sendto_e, &src_dst);
} else {
return(0); /* not a deadlock */
dst_p = _ENDPOINT_P(dst_e);
dst_ptr = proc_addr(dst_p);
- if (dst_ptr->p_rts_flags & NO_ENDPOINT) return EDSTDIED;
+ if (RTS_ISSET(dst_ptr, NO_ENDPOINT)) return EDSTDIED;
/* Check if 'dst' is blocked waiting for this message. The destination's
* SENDING flag may be set when its SENDREC call blocked while sending.
*/
- if ( (dst_ptr->p_rts_flags & (RECEIVING | SENDING)) == RECEIVING &&
+ if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) &&
(dst_ptr->p_getfrom_e == ANY
|| dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) {
/* Destination is indeed waiting for this message. */
CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr,
dst_ptr->p_messbuf);
- if ((dst_ptr->p_rts_flags &= ~RECEIVING) == 0) enqueue(dst_ptr);
+ RTS_UNSET(dst_ptr, RECEIVING);
} else if ( ! (flags & NON_BLOCKING)) {
/* Destination is not waiting. Block and dequeue caller. */
caller_ptr->p_messbuf = m_ptr;
- if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr);
- caller_ptr->p_rts_flags |= SENDING;
+ RTS_SET(caller_ptr, SENDING);
caller_ptr->p_sendto_e = dst_e;
/* Process is now blocked. Put in on the destination's queue. */
else
{
okendpt(src_e, &src_p);
- if (proc_addr(src_p)->p_rts_flags & NO_ENDPOINT) return ESRCDIED;
+ if (RTS_ISSET(proc_addr(src_p), NO_ENDPOINT)) return ESRCDIED;
}
* The caller's SENDING flag may be set if SENDREC couldn't send. If it is
* set, the process should be blocked.
*/
- if (!(caller_ptr->p_rts_flags & SENDING)) {
+ if (!RTS_ISSET(caller_ptr, SENDING)) {
/* Check if there are pending notifications, except for SENDREC. */
if (! (caller_ptr->p_misc_flags & REPLY_PENDING)) {
while (*xpp != NIL_PROC) {
if (src_e == ANY || src_p == proc_nr(*xpp)) {
#if 1
- if ((*xpp)->p_rts_flags & SLOT_FREE)
+ if (RTS_ISSET(*xpp, SLOT_FREE))
{
kprintf("listening to the dead?!?\n");
return EINVAL;
/* Found acceptable message. Copy it and update status. */
CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr);
- if (((*xpp)->p_rts_flags &= ~SENDING) == 0) enqueue(*xpp);
+ RTS_UNSET(*xpp, SENDING);
*xpp = (*xpp)->p_q_link; /* remove from queue */
return(OK); /* report success */
}
if ( ! (flags & NON_BLOCKING)) {
caller_ptr->p_getfrom_e = src_e;
caller_ptr->p_messbuf = m_ptr;
- if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr);
- caller_ptr->p_rts_flags |= RECEIVING;
+ RTS_SET(caller_ptr, RECEIVING);
return(OK);
} else {
return(ENOTREADY);
/* Check to see if target is blocked waiting for this message. A process
* can be both sending and receiving during a SENDREC system call.
*/
- if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
+ if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) &&
! (dst_ptr->p_misc_flags & REPLY_PENDING) &&
(dst_ptr->p_getfrom_e == ANY ||
dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) {
BuildMess(&m, proc_nr(caller_ptr), dst_ptr);
CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m,
dst_ptr, dst_ptr->p_messbuf);
- dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */
- if (dst_ptr->p_rts_flags == 0) enqueue(dst_ptr);
+ RTS_UNSET(dst_ptr, RECEIVING);
return(OK);
}
#include <minix/com.h>
#include "const.h"
#include "priv.h"
-
+
struct proc {
struct stackframe_s p_reg; /* process' registers saved in stack frame */
struct segframe p_seg; /* segment descriptors */
#define NO_PRIV 0x80 /* keep forked system process from running */
#define NO_ENDPOINT 0x100 /* process cannot send or receive messages */
+/* These runtime flags can be tested and manipulated by these macros. */
+
+#define RTS_ISSET(rp, f) (((rp)->p_rts_flags & (f)) == (f))
+
+
+/* Set flag and dequeue if the process was runnable. */
+#define RTS_SET(rp, f) \
+ do { \
+ if(!(rp)->p_rts_flags) { dequeue(rp); } \
+ (rp)->p_rts_flags |= (f); \
+ } while(0)
+
+/* Clear flag and enqueue if the process was not runnable but is now. */
+#define RTS_UNSET(rp, f) \
+ do { \
+ int rts; \
+ rts = (rp)->p_rts_flags; \
+ (rp)->p_rts_flags &= ~(f); \
+ if(rts && !(rp)->p_rts_flags) { enqueue(rp); } \
+ } while(0)
+
+/* Set flag and dequeue if the process was runnable. */
+#define RTS_LOCK_SET(rp, f) \
+ do { \
+ if(!(rp)->p_rts_flags) { lock_dequeue(rp); } \
+ (rp)->p_rts_flags |= (f); \
+ } while(0)
+
+/* Clear flag and enqueue if the process was not runnable but is now. */
+#define RTS_LOCK_UNSET(rp, f) \
+ do { \
+ int rts; \
+ rts = (rp)->p_rts_flags; \
+ (rp)->p_rts_flags &= ~(f); \
+ if(rts && !(rp)->p_rts_flags) { lock_enqueue(rp); } \
+ } while(0)
+
+/* Set flags to this value. */
+#define RTS_LOCK_SETFLAGS(rp, f) \
+ do { \
+ if(!(rp)->p_rts_flags && (f)) { lock_dequeue(rp); } \
+ (rp)->p_rts_flags = (f); \
+ } while(0)
+
/* Misc flags */
#define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */
#define MF_VM 0x08 /* process uses VM */
#include "debug.h"
#include "kernel.h"
#include "system.h"
+#include "proc.h"
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
initialize();
while (TRUE) {
+ int r;
/* Get work. Block and wait until a request message arrives. */
- receive(ANY, &m);
+ if((r=receive(ANY, &m)) != OK) panic("system: receive() failed", r);
sys_call_code = (unsigned) m.m_type;
call_nr = sys_call_code - KERNEL_CALL;
who_e = m.m_source;
} else {
rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */
rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */
- rc->p_priv->s_flags = 0; /* no initial flags */
+
+ /* s_flags of this shared structure are to be once at system startup. */
}
return(OK);
}
rp = proc_addr(proc_nr);
if (! sigismember(&rp->p_pending, sig_nr)) {
sigaddset(&rp->p_pending, sig_nr);
- if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */
- if (rp->p_rts_flags == 0) lock_dequeue(rp); /* make not ready */
- rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */
+ if (! (RTS_ISSET(rp, SIGNALED))) { /* other pending */
+ RTS_LOCK_SET(rp, SIGNALED | SIG_PENDING);
send_sig(PM_PROC_NR, SIGKSIG);
}
}
if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
/* Make sure that the exiting process is no longer scheduled. */
- if (rc->p_rts_flags == 0) lock_dequeue(rc);
- rc->p_rts_flags |= NO_ENDPOINT;
+ RTS_LOCK_SET(rc, NO_ENDPOINT);
/* If the process happens to be queued trying to send a
* message, then it must be removed from the message queues.
*/
- if (rc->p_rts_flags & SENDING) {
+ if (RTS_ISSET(rc, SENDING)) {
int target_proc;
okendpt(rc->p_sendto_e, &target_proc);
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
/* Check if process is receiving from exiting process. */
- if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
+ if (RTS_ISSET(rp, RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
rp->p_reg.retreg = ESRCDIED; /* report source died */
- rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */
+ RTS_LOCK_UNSET(rp, RECEIVING); /* no longer receiving */
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
#endif
- if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
}
- if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
+ if (RTS_ISSET(rp, SENDING) &&
+ rp->p_sendto_e == rc->p_endpoint) {
rp->p_reg.retreg = EDSTDIED; /* report destination died */
- rp->p_rts_flags &= ~SENDING; /* no longer sending */
+ RTS_LOCK_UNSET(rp, SENDING);
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
#endif
- if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
}
}
}
return EINVAL;
rp = proc_addr(proc);
- if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL);
+ if (!RTS_ISSET(rp, SIG_PENDING)) return(EINVAL);
/* PM has finished one kernel signal. Perhaps process is ready now? */
- if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */
- if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */
- lock_enqueue(rp); /* ready if no flags */
+ if (!RTS_ISSET(rp, SIGNALED)) /* new signal arrived */
+ RTS_LOCK_UNSET(rp, SIG_PENDING); /* remove pending flag */
return(OK);
}
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_seg.p_ldt[0]));
#endif
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
- rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
- if (rp->p_rts_flags == 0) lock_enqueue(rp);
+ RTS_LOCK_UNSET(rp, RECEIVING); /* PM does not reply to EXEC call */
/* Save command name for debugging, ps(1) output, etc. */
phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR,
(vir_bytes) P_NAME_LEN - 1);
register struct proc **xpp; /* iterate over caller queue */
int i;
int sys_id;
- char saved_rts_flags;
/* Don't clear if already cleared. */
if(isemptyp(rc)) return;
/* Turn off any alarm timers at the clock. */
reset_timer(&priv(rc)->s_alarm_timer);
- /* Make sure that the exiting process is no longer scheduled. */
- if (rc->p_rts_flags == 0) lock_dequeue(rc);
+ /* Make sure that the exiting process is no longer scheduled,
+ * and mark slot as FREE.
+ */
+ RTS_LOCK_SETFLAGS(rc, SLOT_FREE);
/* Check the table with IRQ hooks to see if hooks should be released. */
for (i=0; i < NR_IRQ_HOOKS; i++) {
* this point. All important fields are reinitialized when the
* slots are assigned to another, new process.
*/
- saved_rts_flags = rc->p_rts_flags;
- rc->p_rts_flags = SLOT_FREE;
if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
/* Clean up virtual memory */
register struct proc *rpc; /* child process pointer */
struct proc *rpp; /* parent process pointer */
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
- int i, gen;
+ int i, gen, r;
int p_proc;
if(!isokendpt(m_ptr->PR_ENDPT, &p_proc))
rpc->p_nr = m_ptr->PR_SLOT; /* this was obliterated by copy */
rpc->p_endpoint = _ENDPOINT(gen, rpc->p_nr); /* new endpoint of slot */
- /* Only one in group should have SIGNALED, child doesn't inherit tracing. */
- rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
- sigemptyset(&rpc->p_pending);
-
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
rpc->p_user_time = 0; /* set all the accounting times to 0 */
rpc->p_sys_time = 0;
m_ptr->PR_ENDPT = rpc->p_endpoint;
/* Install new map */
- return newmap(rpc, map_ptr);
+ r = newmap(rpc, map_ptr);
+
+ /* Only one in group should have SIGNALED, child doesn't inherit tracing. */
+ RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP));
+ sigemptyset(&rpc->p_pending);
+
+ return r;
}
#endif /* USE_FORK */
/* Find the next process with pending signals. */
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
- if (rp->p_rts_flags & SIGNALED) {
+ if (RTS_ISSET(rp, SIGNALED)) {
/* store signaled process' endpoint */
m_ptr->SIG_ENDPT = rp->p_endpoint;
m_ptr->SIG_MAP = rp->p_pending; /* pending signals map */
sigemptyset(&rp->p_pending); /* ball is in PM's court */
- rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */
+ RTS_LOCK_UNSET(rp, SIGNALED); /* blocked by SIG_PENDING */
return(OK);
}
}
register struct proc *rp; /* process whose map is to be loaded */
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
phys_bytes src_phys; /* physical address of map at the PM */
- int old_flags; /* value of flags before modification */
int proc;
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
{
/* Fetch the memory map from PM. */
phys_bytes src_phys; /* physical address of map at the PM */
- int old_flags; /* value of flags before modification */
int proc;
/* Copy the map from PM. */
(phys_bytes)sizeof(rp->p_memmap));
alloc_segments(rp);
- old_flags = rp->p_rts_flags; /* save the previous value of the flags */
- if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
return(OK);
}
rp = proc_addr(proc_nr);
if (pri == PRIO_STOP) {
-
/* Take process off the scheduling queues. */
- if(rp->p_rts_flags == 0) lock_dequeue(rp);
- rp->p_rts_flags |= NO_PRIORITY;
+ RTS_LOCK_SET(rp, NO_PRIORITY);
return(OK);
}
else if (pri >= PRIO_MIN && pri <= PRIO_MAX) {
/* Make sure the process is not running while changing its priority.
* Put the process back in its new queue if it is runnable.
*/
- if(rp->p_rts_flags == 0) lock_dequeue(rp);
- rp->p_rts_flags &= ~NO_PRIORITY;
+ RTS_LOCK_SET(rp, NO_PRIORITY);
rp->p_max_priority = rp->p_priority = new_q;
- if (! rp->p_rts_flags) lock_enqueue(rp);
+ RTS_LOCK_UNSET(rp, NO_PRIORITY);
return(OK);
}
register struct priv *sp;
int proc_nr;
int priv_id;
- int old_flags;
int i;
phys_bytes caller_phys, kernel_phys;
struct io_range io_range;
switch(m_ptr->CTL_REQUEST)
{
case SYS_PRIV_INIT:
- if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM);
+ if (! RTS_ISSET(rp, NO_PRIV)) return(EPERM);
/* Make sure this process has its own privileges structure. This may
* fail, since there are only a limited number of system processes.
}
/* Done. Privileges have been set. Allow process to run again. */
- old_flags = rp->p_rts_flags; /* save value of the flags */
- rp->p_rts_flags &= ~NO_PRIV;
- if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
+ RTS_LOCK_UNSET(rp, NO_PRIV);
return(OK);
case SYS_PRIV_USER:
- if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM);
-
- /* Make this process an ordinary user process.
- */
+ /* Make this process an ordinary user process. */
+ if (!RTS_ISSET(rp, NO_PRIV)) return(EPERM);
if ((i=get_priv(rp, 0)) != OK) return(i);
-
- /* Done. Privileges have been set. Allow process to run again. */
- old_flags = rp->p_rts_flags; /* save value of the flags */
- rp->p_rts_flags &= ~NO_PRIV;
- if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
+ RTS_LOCK_UNSET(rp, NO_PRIV);
return(OK);
case SYS_PRIV_ADD_IO:
- if (rp->p_rts_flags & NO_PRIV)
+ if (RTS_ISSET(rp, NO_PRIV))
return(EPERM);
/* Only system processes get I/O resources? */
return OK;
case SYS_PRIV_ADD_MEM:
- if (rp->p_rts_flags & NO_PRIV)
+ if (RTS_ISSET(rp, NO_PRIV))
return(EPERM);
/* Only system processes get memory resources? */
return OK;
case SYS_PRIV_ADD_IRQ:
- if (rp->p_rts_flags & NO_PRIV)
+ if (RTS_ISSET(rp, NO_PRIV))
return(EPERM);
/* Only system processes get IRQs? */
* EINVAL for grant-out-of-range, in case this turns out to be
* interesting information.)
*/
- if((granter_proc->p_rts_flags & NO_PRIV) || !(priv(granter_proc)) ||
+ if(RTS_ISSET(granter_proc, NO_PRIV) || !(priv(granter_proc)) ||
priv(granter_proc)->s_grant_table < 1) {
kprintf("grant verify failed in ep %d proc %d: "
"no priv table, or no grant table\n",
rp = proc_addr(who_p);
/* Copy grant table set in priv. struct. */
- if ((rp->p_rts_flags & NO_PRIV) || !(priv(rp))) {
+ if (RTS_ISSET(rp, NO_PRIV) || !(priv(rp))) {
r = EPERM;
} else {
_K_SET_GRANT_TABLE(rp,
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
/* Reschedule if necessary. */
- if(rp->p_rts_flags & NO_PRIORITY) {
- rp->p_rts_flags &= ~NO_PRIORITY;
- if (rp->p_rts_flags == 0) lock_enqueue(rp);
- } else kprintf("system: warning: sigsend a running process\n");
+ if(RTS_ISSET(rp, NO_PRIORITY))
+ RTS_LOCK_UNSET(rp, NO_PRIORITY);
+ else
+ kprintf("system: warning: sigsend a running process\n");
return(OK);
}
if (isemptyp(rp)) return(EIO);
switch (tr_request) {
case T_STOP: /* stop process */
- if (rp->p_rts_flags == 0) lock_dequeue(rp);
- rp->p_rts_flags |= P_STOP;
+ RTS_LOCK_SET(rp, P_STOP);
rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
return(OK);
break;
case T_RESUME: /* resume execution */
- rp->p_rts_flags &= ~P_STOP;
- if (rp->p_rts_flags == 0) lock_enqueue(rp);
+ RTS_LOCK_UNSET(rp, P_STOP);
m_ptr->CTL_DATA = 0;
break;
case T_STEP: /* set trace bit */
rp->p_reg.psw |= TRACEBIT;
- rp->p_rts_flags &= ~P_STOP;
- if (rp->p_rts_flags == 0) lock_enqueue(rp);
+ RTS_LOCK_UNSET(rp, P_STOP);
m_ptr->CTL_DATA = 0;
break;
struct irq_hook irq_hooks[NR_IRQ_HOOKS];
int irq_actids[NR_IRQ_VECTORS];
struct irq_hook *e; /* irq tab entry */
- char *irq[] = {
- "clock", /* 00 */
- "keyboard", /* 01 */
- "cascade", /* 02 */
- "rs232", /* 03 */
- "rs232", /* 04 */
- "NIC(eth)", /* 05 */
- "floppy", /* 06 */
- "printer", /* 07 */
- "", /* 08 */
- "", /* 09 */
- "", /* 10 */
- "", /* 11 */
- "", /* 12 */
- "", /* 13 */
- "at_wini_0", /* 14 */
- "at_wini_1", /* 15 */
- };
if ((r = sys_getirqhooks(irq_hooks)) != OK) {
report("IS","warning: couldn't get copy of irq hooks", r);
#endif
printf("IRQ policies dump shows use of kernel's IRQ hooks.\n");
- printf("-h.id- -proc.nr- -IRQ vector (nr.)- -policy- -notify id-\n");
+ printf("-h.id- -proc.nr- -irq nr- -policy- -notify id-\n");
for (i=0; i<NR_IRQ_HOOKS; i++) {
e = &irq_hooks[i];
printf("%3d", i);
continue;
}
printf("%10d ", e->proc_nr_e);
- printf(" %9.9s (%02d) ", irq[e->irq], e->irq);
+ printf(" (%02d) ", e->irq);
printf(" %s", (e->policy & IRQ_REENABLE) ? "reenable" : " - ");
printf(" %d", e->notify_id);
if (irq_actids[e->irq] & (1 << i))
EXTERN struct inode *chroot_dir;
EXTERN short path_processed; /* number of characters processed */
-EXTERN char user_path[PATH_MAX]; /* pathname to be processed */
+EXTERN char user_path[PATH_MAX+1]; /* pathname to be processed */
EXTERN char *vfs_slink_storage;
EXTERN int symloop;
/* Next correct the inode size. */
if(!waspipe) rip->i_size = newsize;
else wipe_inode(rip); /* Pipes can only be truncated to 0. */
+ rip->i_update |= CTIME | MTIME;
rip->i_dirt = DIRTY;
return OK;
for(p = nextblock(start, zone_size)/zone_size; p < e; p ++)
write_map(rip, p*zone_size, NO_ZONE, WMAP_FREE);
+ rip->i_update |= CTIME | MTIME;
+ rip->i_dirt = DIRTY;
+
return OK;
}
case I_REGULAR:
/* Truncate regular file if O_TRUNC. */
if (oflags & O_TRUNC) {
+ panic(__FILE__, "O_TRUNC in mfs.", oflags);
+#if 0
if ((r = forbidden(rip, W_BIT)) !=OK) break;
truncate_inode(rip, 0);
wipe_inode(rip);
* cache flush.
*/
rw_inode(rip, WRITING);
+#endif
}
break;
/* Check length. */
len = fs_m_in.REQ_PATH_LEN;
- if(len > sizeof(string)) return E2BIG; /* too big for buffer */
+ if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */
if(len < 1) return EINVAL; /* too small for \0 */
/* Copy the pathname and set up caller's user and group id */
}
/* Verify this is a null-terminated path. */
- if(user_path[len-1] != '\0')
+ if(user_path[len-1] != '\0') {
+ printf("mfs:lookup: didn't get null-terminated string.\n");
return EINVAL;
+ }
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
rip->i_update |= CTIME;
rip->i_dirt = DIRTY;
+ /* Return full new mode to caller. */
+ fs_m_out.RES_MODE = rip->i_mode;
+
put_inode(rip);
return(OK);
}
rip->i_dirt = DIRTY;
}
+ /* Update caller on current mode, as it may have changed. */
+ fs_m_out.RES_MODE = rip->i_mode;
+
put_inode(rip);
+
return(r);
}
if(endpt == NONE) {
printf("FS: proc with "
"grant %d from %d not found (revive)\n",
- st.m_source,
- st.REP_IO_GRANT);
+ st.REP_IO_GRANT,
+ st.m_source);
continue;
}
}
* The entry points into this file are
* get_fd: look for free file descriptor and free filp slots
* get_filp: look up the filp entry for a given file descriptor
- * find_filp: find a filp slot that points to a given inode
+ * find_filp: find a filp slot that points to a given vnode
* inval_filp: invalidate a filp and associated fd's, only let close()
* happen on it
*/
#include <sys/select.h>
#include <minix/u64.h>
+#include <assert.h>
#include "fs.h"
#include "file.h"
register struct filp *f;
register int i;
- *k = -1; /* we need a way to tell if file desc found */
-
/* Search the fproc fp_filp table for a free file descriptor. */
for (i = start; i < OPEN_MAX; i++) {
if (fp->fp_filp[i] == NIL_FILP && !FD_ISSET(i, &fp->fp_filp_inuse)) {
}
/* Check to see if a file descriptor has been found. */
- if (*k < 0) return(EMFILE); /* this is why we initialized k to -1 */
+ if (i >= OPEN_MAX) return(EMFILE);
/* Now that a file descriptor has been found, look for a free filp slot. */
for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+ assert(f->filp_count >= 0);
if (f->filp_count == 0) {
f->filp_mode = bits;
f->filp_pos = cvu64(0);
*===========================================================================*/
PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits)
{
-/* Find a filp slot that refers to the inode 'rip' in a way as described
+/* Find a filp slot that refers to the vnode 'vp' in a way as described
* by the mode bit 'bits'. Used for determining whether somebody is still
* interested in either end of a pipe. Also used when opening a FIFO to
* find partners to share a filp field with (to shared the file position).
for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)){
+ assert(f->filp_count > 0);
return(f);
}
}
EXTERN int call_nr; /* system call number */
EXTERN message mount_m_in; /* the input message itself */
-EXTERN char user_fullpath[PATH_MAX]; /* storage for user path name */
+EXTERN char user_fullpath[PATH_MAX+1]; /* storage for user path name */
EXTERN short cum_path_processed; /* number of characters processed */
/* The following variables are used for returning results to the caller. */
panic(__FILE__, "check_vrefs failed at line", __LINE__);
}
#endif
+
+
}
return(OK); /* shouldn't come here */
}
}
for(;;) {
+ int r;
/* Normal case. No one to revive. */
- if (receive(ANY, &m_in) != OK)
- panic(__FILE__,"fs receive error", NO_NUM);
+ if ((r=receive(ANY, &m_in)) != OK)
+ panic(__FILE__,"fs receive error", r);
who_e = m_in.m_source;
who_p = _ENDPOINT_P(who_e);
}
if (count > 1) {
- printf("VFSunmount: %d filesystem is busy count: %d\n", dev, count);
return(EBUSY); /* can't umount a busy file system */
}
#include "lock.h"
#include "param.h"
#include <dirent.h>
+#include <assert.h>
#include <minix/vfsif.h>
#include "vnode.h"
vp= NULL;
-#if 0
- printf("common_open: for '%s'\n", user_fullpath);
-#endif
-
/* Fill in lookup request fields */
Xlookup_req.path = user_fullpath;
Xlookup_req.lastc = Xlastc;
{
if (pathrem == NULL)
panic(__FILE__, "no pathrem", NO_NUM);
- if (strchr(pathrem, '/') == 0)
+
+ /* If any path remains, but no '/', O_CREAT can continue.
+ * If no path remains, a null filename was provided so ENOENT
+ * remains.
+ */
+ if(*pathrem) {
+ if (strchr(pathrem, '/') == 0)
r= OK;
- else
- {
+ else
+ {
printf("common_open: / in pathrem\n");
+ }
}
}
break;
case I_NAMED_PIPE:
- printf("common_open: setting I_PIPE, inode %d on dev 0x%x\n",
- vp->v_inode_nr, vp->v_dev);
vp->v_pipe = I_PIPE;
vp->v_isfifo= TRUE;
oflags |= O_APPEND; /* force append mode */
* file position will be automatically shared.
*/
b = (bits & R_BIT ? R_BIT : W_BIT);
+ assert(fil_ptr->filp_count == 1);
fil_ptr->filp_count = 0; /* don't find self */
if ((filp2 = find_filp(vp, b)) != NIL_FILP) {
/* Co-reader or writer found. Use it.*/
break;
case I_NAMED_PIPE:
- printf("x_open (fifo): reference count %d, fd %d\n",
- vp->v_ref_count, vp->v_fs_count);
if (vp->v_ref_count == 1)
{
- printf("x_open (fifo): first reference, size %u\n",
- vp->v_size);
if (vp->v_size != 0)
{
- printf("x_open (fifo): clearing\n");
r= truncate_vn(vp, 0);
if (r != OK)
{
* processes hanging on the pipe.
*/
- printf("pipe_open: setting I_PIPE, inode %d on dev 0x%x\n",
- vp->v_inode_nr, vp->v_dev);
vp->v_pipe = I_PIPE;
if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) {
/* If a write has been done, the inode is already marked as DIRTY. */
if (--rfilp->filp_count == 0) {
+ if (vp->v_pipe == I_PIPE) {
+ /* Last reader or writer is going. Tell MFS about latest
+ * pipe size.
+ */
+ truncate_vn(vp, vp->v_size);
+ }
if (vp->v_pipe == I_PIPE && vp->v_ref_count > 1) {
/* Save the file position in the v-node in case needed later.
* The read and write positions are saved separately.
/* Empty (start) path? */
if (fullpath[0] == '\0') {
+ node->inode_nr = 0;
return ENOENT;
}
/* Empty (start) path? */
if (fullpath[0] == '\0') {
+ node->inode_nr = 0;
+ *pathrem = fullpath;
return ENOENT;
}
if (res.inode_nr == 0)
{
printf("lookup_vp: lookup returned no inode\n");
- printf("lookup_res = %d, last = '%s'\n",
+ printf("lookup_res = %d, last = '%s'\n\n",
lookup_res, lookup_req->lastc);
*vpp= NULL;
return lookup_res;
if (res.inode_nr == 0)
{
printf("Xlookup_vp: lookup returned no inode\n");
- printf("lookup_res = %d, last = '%s'\n",
+ printf("lookup_res = %d, last = '%s'\n\n",
lookup_res, lookup_req->lastc);
*vpp= NULL;
return lookup_res;
struct chmod_req req;
struct lookup_req lookup_req;
struct node_details res;
- int r;
+ struct vnode *vp;
+ int r, ch_mode;
if (call_nr == CHMOD) {
/* Perform the chmod(name, mode) system call. */
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
+ /* Find vnode, if it's in use. */
+ vp = find_vnode(req.fs_e, req.inode_nr);
+
/* Fill in request message fields.*/
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.rmode = m_in.mode;
/* Issue request */
- return req_chmod(&req);
+ if((r = req_chmod(&req, &ch_mode)) != OK) return r;
+
+ if(vp != NIL_VNODE)
+ vp->v_mode = ch_mode;
+
+ return OK;
}
/*===========================================================================*
struct chown_req req;
struct lookup_req lookup_req;
struct node_details res;
- int r;
+ struct vnode *vp;
+ int r, ch_mode;
if (call_nr == CHOWN) {
/* Perform the chmod(name, mode) system call. */
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
+ /* Find vnode, if it's in use. */
+ vp = find_vnode(req.fs_e, req.inode_nr);
+
/* Fill in request message fields.*/
req.uid = fp->fp_effuid;
req.gid = fp->fp_effgid;
req.newgid = m_in.group;
/* Issue request */
- return req_chown(&req);
+ r = req_chown(&req, &ch_mode);
+
+ if(r == OK && vp) {
+ vp->v_uid = m_in.owner;
+ vp->v_gid = m_in.group;
+ vp->v_mode = ch_mode;
+ }
+
+ return r;
}
/* If access desired is not a subset of what is allowed, it is refused. */
r = OK;
- if ((perm_bits | access_desired) != perm_bits) r = EACCES;
+ if ((perm_bits | access_desired) != perm_bits) {
+ r = EACCES;
+ }
/* Check to see if someone is trying to write on a file system that is
* mounted read-only.
_PROTOTYPE( int read_write, (int rw_flag) );
/* request.c */
-_PROTOTYPE( int req_getnode, (node_req_t *req, node_details_t *res) );
+#define req_getnode(req, res) req_getnode_f(__FILE__, __LINE__, (req), (res))
+_PROTOTYPE( int req_getnode_f, (char *file, int line, node_req_t *req, node_details_t *res) );
_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) );
_PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) );
_PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
_PROTOTYPE( int req_clone_opcl, (clone_opcl_req_t *req,
node_details_t *res) );
_PROTOTYPE( int req_ftrunc, (ftrunc_req_t *req) );
-_PROTOTYPE( int req_chown, (chown_req_t *req) );
-_PROTOTYPE( int req_chmod, (chmod_req_t *req) );
+_PROTOTYPE( int req_chown, (chown_req_t *req, int *mode) );
+_PROTOTYPE( int req_chmod, (chmod_req_t *req, int *mode) );
_PROTOTYPE( int req_access, (access_req_t *req) );
_PROTOTYPE( int req_mknod, (mknod_req_t *req) );
_PROTOTYPE( int req_mkdir, (mkdir_req_t *req) );
_PROTOTYPE( void fs_cancel_timer, (timer_t *tp) );
_PROTOTYPE( void fs_init_timer, (timer_t *tp) );
+
#include "fproc.h"
#include "param.h"
#include <dirent.h>
+#include <assert.h>
#include <minix/vfsif.h>
#include "vnode.h"
/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
register struct filp *f;
register struct vnode *vp;
- off_t bytes_left, f_size;
+ off_t bytes_left;
u64_t position;
unsigned int off, cum_io;
int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
oflags = f->filp_flags;
vp = f->filp_vno;
- f_size = vp->v_size;
r = OK;
if (vp->v_pipe == I_PIPE) {
}
if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
- f_size = ULONG_MAX;
if (vp->v_sdev == NO_DEV)
panic(__FILE__,"read_write tries to read from "
" block device NO_DEV", NO_NUM);
position = res.new_pos;
cum_io += res.cum_io;
}
- /* Regular files */
+ /* Regular files (and pipes) */
else {
if (rw_flag == WRITING && block_spec == 0) {
/* Check for O_APPEND flag. */
- if (oflags & O_APPEND) position = cvul64(f_size);
+ if (oflags & O_APPEND) position = cvul64(vp->v_size);
/* Check in advance to see if file will grow too big. */
if (cmp64ul(position, vp->v_vmnt->m_max_file_size - m_in.nbytes) > 0)
}
if (partial_cnt > 0) {
- /* So taht we don't need to deal with partial count
- * in the FS process */
+ /* So that we don't need to deal with partial count
+ * in the FS process.
+ */
m_in.nbytes = MIN(m_in.nbytes, partial_cnt);
partial_pipe = 1;
}
req.user_addr = m_in.buffer;
req.inode_index = vp->v_index;
- if (vp->v_isfifo)
- {
- printf("read_write: %s for FIFO @ %u size %u\n",
- (rw_flag == READING) ? "read" : "write",
- ex64lo(position), m_in.nbytes);
+ /* Truncate read request at size (mustn't do this for special files). */
+ if((rw_flag == READING) &&
+ cmp64ul(add64ul(position, req.num_of_bytes), vp->v_size) > 0) {
+ /* Position always should fit in an off_t (LONG_MAX). */
+ off_t pos32;
+ assert(cmp64ul(position, LONG_MAX) <= 0);
+ pos32 = cv64ul(position);
+ assert(pos32 >= 0);
+ assert(pos32 <= LONG_MAX);
+ req.num_of_bytes = vp->v_size - pos32;
+ assert(req.num_of_bytes >= 0);
}
/* Issue request */
/* On write, update file size and access time. */
if (rw_flag == WRITING) {
if (regular || mode_word == I_DIRECTORY) {
- if (cmp64ul(position, f_size) > 0)
+ if (cmp64ul(position, vp->v_size) > 0)
{
if (ex64hi(position) != 0)
{
#include "vnode.h"
#include "param.h"
-FORWARD _PROTOTYPE(int fs_sendrec, (endpoint_t fs_e, message *reqm));
+FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm));
+
+#define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m))
/*===========================================================================*
* req_getnode *
*===========================================================================*/
-PUBLIC int req_getnode(req, res)
+PUBLIC int req_getnode_f(file, line, req, res)
+char *file;
+int line;
node_req_t *req;
node_details_t *res;
{
/*===========================================================================*
* req_chmod *
*===========================================================================*/
-PUBLIC int req_chmod(req)
+PUBLIC int req_chmod(req, ch_mode)
chmod_req_t *req;
+int *ch_mode;
{
message m;
+ int r;
/* Fill in request message */
m.m_type = REQ_CHMOD;
m.REQ_GID = req->gid;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(req->fs_e, &m);
+
+ /* Copy back actual mode. */
+ if(ch_mode) *ch_mode = m.RES_MODE;
+
+ return r;
}
/*===========================================================================*
* req_chown *
*===========================================================================*/
-PUBLIC int req_chown(req)
+PUBLIC int req_chown(req, ch_mode)
chown_req_t *req;
+int *ch_mode;
{
message m;
+ int r;
/* Fill in request message */
m.m_type = REQ_CHOWN;
m.REQ_NEW_GID = req->newgid;
/* Send/rec request */
- return fs_sendrec(req->fs_e, &m);
+ r = fs_sendrec(req->fs_e, &m);
+
+ /* Return new mode to caller. */
+ if(ch_mode) *ch_mode = m.RES_MODE;
+
+ return r;
}
/*===========================================================================*
* fs_sendrec *
*===========================================================================*/
-PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm)
+PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm)
{
/* This is the low level function that sends requests to FS processes.
* It also handles driver recovery mechanism and reissuing the
int r, old_driver_e, new_driver_e;
message origm, m;
struct vmnt *vmp;
-
+
/* Make a copy of the request so that we can load it back in
* case of a dead driver */
origm = *reqm;
for (;;) {
/* Do the actual send, receive */
if (OK != (r=sendrec(fs_e, reqm))) {
- printf("VFS: error sending message. FS_e: %d req_nr: %d err: %d\n",
- fs_e, reqm->m_type, r);
+ printf("VFS:fs_sendrec:%s:%d: error sending message. FS_e: %d req_nr: %d err: %d\n",
+ file, line, fs_e, reqm->m_type, r);
}
if(r == OK) {
/* Dead driver */
if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
old_driver_e = NONE;
- /* Find old driver enpoint */
+ /* Find old driver by endpoint */
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
- if (vmp->m_fs_e == reqm->m_source) { /* found FS */
+ if (vmp->m_fs_e == fs_e) { /* found FS */
old_driver_e = vmp->m_driver_e;
dmap_unmap_by_endpt(old_driver_e); /* unmap driver */
break;
}
/* No FS ?? */
- if (old_driver_e == NONE) {
- panic(__FILE__, "VFSdead_driver: couldn't find FS\n",
- old_driver_e);
- }
+ if (old_driver_e == NONE)
+ panic(__FILE__, "VFSdead_driver: couldn't find FS\n", fs_e);
/* Wait for a new driver. */
for (;;) {
put_vnode(vp);
return ENOTDIR;
}
-
+
+ /* Access check */
+ r = forbidden(vp, X_BIT);
+ if (r != OK) {
+ put_vnode(vp);
+ return r;
+ }
+
return change_into(iip, vp);
}
#include "file.h"
#include "fproc.h"
#include "param.h"
+#include "vmnt.h"
PRIVATE int panicking; /* inhibits recursive panics during sync */
register char *rpu, *rpm;
int r;
+ if (len > PATH_MAX) {
+ err_code = ENAMETOOLONG;
+ return(EGENERIC);
+ }
+
if(len >= sizeof(user_fullpath)) {
panic(__FILE__, "fetch_name: len too much for user_fullpath", len);
}
/* Check name length for validity. */
if (len <= 0) {
err_code = EINVAL;
- return(EGENERIC);
- }
-
- if (len > PATH_MAX) {
- err_code = ENAMETOOLONG;
+ printf("vfs: fetch_name: len %d?\n", len);
return(EGENERIC);
}
if (panicking) return; /* do not panic during a sync */
panicking = TRUE; /* prevent another panic during the sync */
- printf("FS panic (%s): %s ", who, mess);
+ printf("VFS panic (%s): %s ", who, mess);
if (num != NO_NUM) printf("%d",num);
(void) do_sync(); /* flush everything to the disk */
sys_exit(SELF);
return( (time_t) (boottime + (uptime/HZ)));
}
-