static void print_proc_depends(struct proc *pp, const int level)
{
	struct proc *depproc = NULL;
	endpoint_t dep;
#define COL { int i; for(i = 0; i < level; i++) printf("> "); }

	if(level >= NR_PROCS) {
		printf("loop??\n");
		return;
	}

	COL

	print_proc(pp);

	COL
	proc_stacktrace(pp);


	dep = P_BLOCKEDON(pp);
	if(dep != NONE && dep != ANY) {
		int procno;
		if(isokendpt(dep, &procno)) {
			depproc = proc_addr(procno);
			if(isemptyp(depproc))
				depproc = NULL;
		}
		if (depproc)
			print_proc_depends(depproc, level+1);
	}
}
void print_proc(struct proc *pp)
{
	endpoint_t dep;

	printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d "
			"pdbr 0x%lx rts %s misc %s sched %s ",
		proc_nr(pp), pp->p_name, pp->p_endpoint, 
		pp->p_priority, pp->p_user_time,
		pp->p_sys_time, ex64hi(pp->p_cycles),
		ex64lo(pp->p_cycles), pp->p_cpu,
#if defined(__i386__)
		pp->p_seg.p_cr3,
#elif defined(__arm__)
		pp->p_seg.p_ttbr,
#endif
		rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
		schedulerstr(pp->p_scheduler));

	print_sigmgr(pp);

	dep = P_BLOCKEDON(pp);
	if(dep != NONE) {
		printf(" blocked on: ");
		print_endpoint(dep);
	}
	printf("\n");
}
Ejemplo n.º 3
0
PUBLIC void print_proc(struct proc *pp)
{
	struct proc *depproc = NULL;
	endpoint_t dep;

	printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cpu %2d "
			"cr3 0x%lx rts %s misc %s sched %s ",
		proc_nr(pp), pp->p_name, pp->p_endpoint, 
		pp->p_priority, pp->p_user_time,
		pp->p_sys_time, ex64hi(pp->p_cycles),
		ex64lo(pp->p_cycles), pp->p_cpu,
		pp->p_seg.p_cr3,
		rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
		schedulerstr(pp->p_scheduler));

	print_sigmgr(pp);

	dep = P_BLOCKEDON(pp);
	if(dep != NONE) {
		printf(" blocked on: ");
		print_endpoint(dep);
	}
	printf("\n");
}
Ejemplo n.º 4
0
void print_procs(int maxlines,
	struct proc *proc1, struct proc *proc2,
	struct mproc *mproc)
{
	int p, nprocs, tot=0;
	u64_t idleticks = cvu64(0);
	u64_t kernelticks = cvu64(0);
	u64_t systemticks = cvu64(0);
	u64_t userticks = cvu64(0);
	u64_t total_ticks = cvu64(0);
	unsigned long tcyc;
	unsigned long tmp;
	int blockedseen = 0;
	struct tp tick_procs[PROCS];

	for(p = nprocs = 0; p < PROCS; p++) {
		if(isemptyp(&proc2[p]))
			continue;
		tick_procs[nprocs].p = proc2 + p;
		if(proc1[p].p_endpoint == proc2[p].p_endpoint) {
			tick_procs[nprocs].ticks =
				sub64(proc2[p].p_cycles, proc1[p].p_cycles);
		} else {
			tick_procs[nprocs].ticks =
				proc2[p].p_cycles;
		}
		total_ticks = add64(total_ticks, tick_procs[nprocs].ticks);
		if(p-NR_TASKS == IDLE) {
			idleticks = tick_procs[nprocs].ticks;
			continue;
		}
		if(p-NR_TASKS == KERNEL) {
			kernelticks = tick_procs[nprocs].ticks;
			continue;
		}
		if(mproc[proc2[p].p_nr].mp_procgrp == 0)
			systemticks = add64(systemticks, tick_procs[nprocs].ticks);
		else if (p > NR_TASKS)
			userticks = add64(userticks, tick_procs[nprocs].ticks);

		nprocs++;
	}

	if (!cmp64u(total_ticks, 0))
		return;

	qsort(tick_procs, nprocs, sizeof(tick_procs[0]), cmp_ticks);

	tcyc = div64u(total_ticks, SCALE);

	tmp = div64u(userticks, SCALE);
	printf("CPU states: %6.2f%% user, ", 100.0*(tmp)/tcyc);

	tmp = div64u(systemticks, SCALE);
	printf("%6.2f%% system, ", 100.0*tmp/tcyc);

	tmp = div64u(kernelticks, SCALE);
	printf("%6.2f%% kernel, ", 100.0*tmp/tcyc);

	tmp = div64u(idleticks, SCALE);
	printf("%6.2f%% idle", 100.0*tmp/tcyc);

#define NEWLINE do { printf("\n"); if(--maxlines <= 0) { return; } } while(0) 
	NEWLINE;
	NEWLINE;

	printf("  PID USERNAME PRI NICE   SIZE STATE   TIME     CPU COMMAND");
	NEWLINE;
	for(p = 0; p < nprocs; p++) {
		struct proc *pr;
		int pnr;
		int level = 0;

		pnr = tick_procs[p].p->p_nr;

		if(pnr < 0) {
			/* skip old kernel tasks as they don't run anymore */
			continue;
		}

		pr = tick_procs[p].p;

		/* If we're in blocked verbose mode, indicate start of
		 * blocked processes.
		 */
		if(blockedverbose && pr->p_rts_flags && !blockedseen) {
			NEWLINE;
			printf("Blocked processes:");
			NEWLINE;
			blockedseen = 1;
		}

		print_proc(&tick_procs[p], &mproc[pnr], tcyc);
		NEWLINE;

		if(!blockedverbose)
			continue;

		/* Traverse dependency chain if blocked. */
		while(pr->p_rts_flags) {
			endpoint_t dep = NONE;
			struct tp *tpdep;
			level += 5;

			if((dep = P_BLOCKEDON(pr)) == NONE) {
				printf("not blocked on a process");
				NEWLINE;
				break;
			}

			if(dep == ANY)
				break;

			tpdep = lookup(dep, tick_procs, nprocs);
			pr = tpdep->p;
			printf("%*s> ", level, "");
			print_proc(tpdep, &mproc[pr->p_nr], tcyc);
			NEWLINE;
		}
	}
}
/*
 * Return the LWP status of a process, along with additional information in
 * case the process is sleeping (LSSLEEP): a wchan value and text to indicate
 * what the process is sleeping on, and possibly a flag field modification to
 * indicate that the sleep is interruptible.
 */
static int
get_lwp_stat(int mslot, uint64_t * wcptr, char * wmptr, size_t wmsz,
	int32_t * flag)
{
	struct mproc *mp;
	struct fproc_light *fp;
	struct proc *kp;
	const char *wmesg;
	uint64_t wchan;
	endpoint_t endpt;

	mp = &mproc_tab[mslot];
	fp = &fproc_tab[mslot];
	kp = &proc_tab[NR_TASKS + mslot];

	/*
	 * First cover all the cases that the process is not sleeping.  In
	 * those cases, we need not return additional sleep information either.
	 */
	if (mp->mp_flags & (TRACE_ZOMBIE | ZOMBIE))
		return LSZOMB;

	if (mp->mp_flags & EXITING)
		return LSDEAD;

	if ((mp->mp_flags & TRACE_STOPPED) || RTS_ISSET(kp, RTS_P_STOP))
		return LSSTOP;

	if (proc_is_runnable(kp))
		return LSRUN;

	/*
	 * The process is sleeping.  In that case, we must also figure out why,
	 * and return an appropriate wchan value and human-readable wmesg text.
	 *
	 * The process can be blocked on either a known sleep state in PM or
	 * VFS, or otherwise on IPC communication with another process, or
	 * otherwise on a kernel RTS flag.  In each case, decide what to use as
	 * wchan value and wmesg text, and whether the sleep is interruptible.
	 *
	 * The wchan value should be unique for the sleep reason.  We use its
	 * lower eight bits to indicate a class:
	 *   0x00 = kernel task
	 *   0x01 = kerel RTS block
	 *   0x02 = PM call
	 *   0x03 = VFS call
	 *   0x04 = MIB call
	 *   0xff = blocked on process
	 * The upper bits are used for class-specific information.  The actual
	 * value does not really matter, as long as it is nonzero and there is
	 * no overlap between the different values.
	 */
	wchan = 0;
	wmesg = NULL;

	/*
	 * First see if the process is marked as blocked in the tables of PM or
	 * VFS.  Such a block reason is always an interruptible sleep.  Note
	 * that we do not use the kernel table at all in this case: each of the
	 * three tables is consistent within itself, but not necessarily
	 * consistent with any of the other tables, so we avoid internal
	 * mismatches if we can.
	 */
	if (mp->mp_flags & WAITING) {
		wchan = 0x102;
		wmesg = "wait";
	} else if (mp->mp_flags & SIGSUSPENDED) {
		wchan = 0x202;
		wmesg = "pause";
	} else if (fp->fpl_blocked_on != FP_BLOCKED_ON_NONE) {
		wchan = (fp->fpl_blocked_on << 8) | 0x03;
		switch (fp->fpl_blocked_on) {
		case FP_BLOCKED_ON_PIPE:
			wmesg = "pipe";
			break;
		case FP_BLOCKED_ON_FLOCK:
			wmesg = "flock";
			break;
		case FP_BLOCKED_ON_POPEN:
			wmesg = "popen";
			break;
		case FP_BLOCKED_ON_SELECT:
			wmesg = "select";
			break;
		case FP_BLOCKED_ON_CDEV:
		case FP_BLOCKED_ON_SDEV:
			/*
			 * Add the task (= character or socket driver) endpoint
			 * to the wchan value, and use the driver's process
			 * name, without parentheses, as wmesg text.
			 */
			wchan |= (uint64_t)fp->fpl_task << 16;
			fill_wmesg(wmptr, wmsz, fp->fpl_task, FALSE /*ipc*/);
			break;
		default:
			/* A newly added flag we don't yet know about? */
			wmesg = "???";
			break;
		}
	}
	if (wchan != 0) {
		*wcptr = wchan;
		if (wmesg != NULL) /* NULL means "already set" here */
			strlcpy(wmptr, wmesg, wmsz);
		*flag |= L_SINTR;
	}

	/*
	 * See if the process is blocked on sending or receiving.  If not, then
	 * use one of the kernel RTS flags as reason.
	 */
	endpt = P_BLOCKEDON(kp);

	switch (endpt) {
	case MIB_PROC_NR:
		/* This is really just aesthetics. */
		wchan = 0x04;
		wmesg = "sysctl";
		break;
	case NONE:
		/*
		 * The process is not running, but also not blocked on IPC with
		 * another process.  This means it must be stopped on a kernel
		 * RTS flag.
		 */
		wchan = ((uint64_t)kp->p_rts_flags << 8) | 0x01;
		if (RTS_ISSET(kp, RTS_PROC_STOP))
			wmesg = "kstop";
		else if (RTS_ISSET(kp, RTS_SIGNALED) ||
		    RTS_ISSET(kp, RTS_SIGNALED))
			wmesg = "ksignal";
		else if (RTS_ISSET(kp, RTS_NO_PRIV))
			wmesg = "knopriv";
		else if (RTS_ISSET(kp, RTS_PAGEFAULT) ||
		    RTS_ISSET(kp, RTS_VMREQTARGET))
			wmesg = "fault";
		else if (RTS_ISSET(kp, RTS_NO_QUANTUM))
			wmesg = "sched";
		else
			wmesg = "kflag";
		break;
	case ANY:
		/*
		 * If the process is blocked receiving from ANY, mark it as
		 * being in an interruptible sleep.  This looks nicer, even
		 * though "interruptible" is not applicable to services at all.
		 */
		*flag |= L_SINTR;
		break;
	}

	/*
	 * If at this point wchan is still zero, the process is blocked sending
	 * or receiving.  Use a wchan value based on the target endpoint, and
	 * use "(procname)" as wmesg text.
	 */
	if (wchan == 0) {
		*wcptr = ((uint64_t)endpt << 8) | 0xff;
		fill_wmesg(wmptr, wmsz, endpt, TRUE /*ipc*/);
	} else {
		*wcptr = wchan;
		if (wmesg != NULL) /* NULL means "already set" here */
			strlcpy(wmptr, wmesg, wmsz);
	}

	return LSSLEEP;
}