Пример #1
0
static void
imagereclaim(void)
{
	Image *i;
	uvlong ticks0, ticks;

	irstats.calls++;
	/* Somebody is already cleaning the page cache */
	if(!canqlock(&imagealloc.ireclaim))
		return;
	DBG("imagereclaim maxt %ulld noluck %d nolock %d\n",
		irstats.maxt, irstats.noluck, irstats.nolock);
	ticks0 = fastticks(nil);
	if(!canlock(&imagealloc)){
		/* never happen in the experiments I made */
		qunlock(&imagealloc.ireclaim);
		return;
	}

	for(i = imagealloc.lru; i != nil; i = i->prev){
		if(canlock(i)){
			i->ref++;	/* make sure it does not go away */
			unlock(i);
			pagereclaim(i);
			lock(i);
			DBG("imagereclaim: image %p(c%p, r%d)\n", i, i->c, i->ref);
			if(i->ref == 1){	/* no pages referring to it, it's ours */
				unlock(i);
				unlock(&imagealloc);
				putimage(i);
				break;
			}else
				--i->ref;
			unlock(i);
		}
	}

	if(i == nil){
		irstats.noluck++;
		unlock(&imagealloc);
	}
	irstats.loops++;
	ticks = fastticks(nil) - ticks0;
	irstats.ticks += ticks;
	if(ticks > irstats.maxt)
		irstats.maxt = ticks;
	//print("T%llud+", ticks);
	qunlock(&imagealloc.ireclaim);
}
Пример #2
0
void
qunlock(QLock *q)
{
	Proc *p;
	uint64_t t0;

	if(!canlock(&q->use)){
		cycles(&t0);
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	if (q->locked == 0)
		print("qunlock called with qlock not held, from %#p\n",
			getcallerpc(&q));
	p = q->head;
	if(p){
		q->head = p->qnext;
		if(q->head == 0)
			q->tail = 0;
		unlock(&q->use);
		q->pc = p->qpc;
		ready(p);
		return;
	}
	q->locked = 0;
	q->pc = 0;
	unlock(&q->use);
}
Пример #3
0
/*
 * Called from imagereclaim, to try to release Images.
 * The argument shows the preferred image to release pages from.
 * All images will be tried, from lru to mru.
 */
uint64_t
pagereclaim(Image *i)
{
	Page *p;
	uint64_t ticks;

	lock(&pga.l);
	ticks = fastticks(nil);

	/*
	 * All the pages with images backing them are at the
	 * end of the list (see putpage) so start there and work
	 * backward.
	 */
	for(p = pga.pgsza[0].tail; p && p->image == i; p = p->prev){
		if(p->ref == 0 && canlock(&p->l)){
			if(p->ref == 0) {
				uncachepage(p);
			}
			unlock(&p->l);
		}
	}
	ticks = fastticks(nil) - ticks;
	unlock(&pga.l);

	return ticks;
}
Пример #4
0
void
_threadnote(void *v, char *s)
{
	Proc *p;
	Note *n;

	_threaddebug(DBGNOTE, "Got note %s", s);
//	if(strncmp(s, "sys:", 4) == 0)
//		noted(NDFLT);

//	if(_threadexitsallstatus){
//		_threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus);
//		_exits(_threadexitsallstatus);
//	}

	if(strcmp(s, "threadint")==0)
		noted(NCONT);

	p = _threadgetproc();
	if(p == nil)
		noted(NDFLT);

	for(n=notes; n<enotes; n++)
		if(canlock(&n->inuse))
			break;
	if(n==enotes)
		sysfatal("libthread: too many delayed notes");
	utfecpy(n->s, n->s+ERRMAX, s);
	n->proc = p;
	p->pending = 1;
	if(!p->splhi)
		delayednotes(p, v);
	noted(NCONT);
}
Пример #5
0
Файл: clock.c Проект: 8l/inferno
static void
clockintr(Ureg*, void*)
{
	Clock0link *lp;
	int losttick = 0;
	OstmrReg *ost = OSTMRREG;

{static int tag, led; if(++tag >= HZ){ledset(led ^= 1);tag=0;}}
	m->ticks++;
//	ost->osmr[3] = ost->oscr + timer_incr[3]; /* restart the watchdog */
	ost->osmr[0] += timer_incr[0];		/* advance the clock tick */
	ost->ossr = (1<<0); 			/* Clear the SR */

	while((ost->osmr[0] - ost->oscr) >= 0x80000000) {
		ost->osmr[0] += timer_incr[0]; 
		losttick++;
		m->ticks++;
	}

	checkalarms();

	if(canlock(&clock0lock)){
		for(lp = clock0link; lp; lp = lp->link)
			if(lp->clock)
				lp->clock();
		unlock(&clock0lock);
	}

	/* round robin time slice is done by trap.c and proc.c */
}
Пример #6
0
void
runlock(RWlock *q)
{
	Proc *p;
	uint64_t t0;

	if(!canlock(&q->use)){
		cycles(&t0);
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	p = q->head;
	if(--(q->readers) > 0 || p == nil){
		unlock(&q->use);
		return;
	}

	/* start waiting writer */
	if(p->state != QueueingW)
		panic("runlock");
	q->head = p->qnext;
	if(q->head == 0)
		q->tail = 0;
	q->writer = 1;
	unlock(&q->use);
	ready(p);
}
Пример #7
0
static void
myscreenputs(char *s, int n)
{
	int i;
	Rune r;
	char buf[4];

	if(!islo()) {
		/* don't deadlock trying to print in interrupt */
		if(!canlock(&screenlock))
			return;	
	}
	else
		lock(&screenlock);

	while(n > 0){
		i = chartorune(&r, s);
		if(i == 0){
			s++;
			--n;
			continue;
		}
		memmove(buf, s, i);
		buf[i] = 0;
		n -= i;
		s += i;
		screenputc(buf);
	}
	unlock(&screenlock);
}
Пример #8
0
Файл: alarm.c Проект: 8l/inferno
/*
 *  called every clock tick
 */
void
checkalarms(void)
{
	Proc *p;
	ulong now;

	now = MACHP(0)->ticks;

	if(talarm.list == 0 || canlock(&talarm) == 0)
		return;

	for(;;) {
		p = talarm.list;
		if(p == 0)
			break;

		if(p->twhen == 0) {
			talarm.list = p->tlink;
			p->trend = 0;
			continue;
		}
		if(now < p->twhen)
			break;
		wakeup(p->trend);
		talarm.list = p->tlink;
		p->trend = 0;
	}

	unlock(&talarm);
}
Пример #9
0
void
exit(int ispanic)
{
	canlock(&active);
	active.machs &= ~(1<<m->machno);
	active.exiting = 1;
	unlock(&active);

	spllo();
	print("cpu %d exiting\n", m->machno);
	do
		delay(100);
	while(consactive());

	splhi();
	delay(1000);	/* give serial fifo time to finish flushing */
	if (getconf("*debug") != nil) {
		USED(ispanic);
		delay(60*1000);		/* give us time to read the screen */
	}
	if(arch->coredetach)
		arch->coredetach();
	setupboot(1);			// set up to halt
	for (; ; )
		firmware();

	// on PC is just:
	//if (0) {
	//	shutdown(ispanic);
	//	arch->reset();
	//}
}
Пример #10
0
int
canqlock(QLock *q)
{
	if(!canlock(&q->use))
		return 0;
	if(q->locked){
		unlock(&q->use);
		return 0;
	}
	q->locked = 1;
	unlock(&q->use);
	return 1;
}
Пример #11
0
int
canqlock(QLock *q)
{
	if(!canlock(&q->lock))
		return 0;
	if(!q->locked){
		q->locked = 1;
		unlock(&q->lock);
		return 1;
	}
	unlock(&q->lock);
	return 0;
}
Пример #12
0
int
canqlock(QLock *q)
{
	if(!canlock(&q->use))
		return 0;
	if(q->locked){
		unlock(&q->use);
		return 0;
	}
	q->locked = 1;
	q->qpc = getcallerpc(&q);
	unlock(&q->use);
	return 1;
}
Пример #13
0
static int
iprintcanlock(Lock *l)
{
	int i;

	for(i=0; i<1000; i++){
		if(canlock(l))
			return 1;
		if(l->m == machp())
			return 0;
		microdelay(100);
	}
	return 0;
}
Пример #14
0
void
mpshutdown(void)
{
	/*
	 * To be done...
	 */
	if(!canlock(&mpshutdownlock)){
		/*
		 * If this processor received the CTRL-ALT-DEL from
		 * the keyboard, acknowledge it. Send an INIT to self.
		 */
#ifdef FIXTHIS
		if(lapicisr(VectorKBD))
			lapiceoi(VectorKBD);
#endif /* FIX THIS */
		arch->introff();
		idle();
	}

	if(active.rebooting)
		return;
	print("apshutdown: active = %#8.8ux\n", active.machs);
	delay(1000);
	splhi();
	arch->resetothers();

	pcireset();
	i8042reset();

	/*
	 * Often the BIOS hangs during restart if a conventional 8042
	 * warm-boot sequence is tried. The following is Intel specific and
	 * seems to perform a cold-boot, but at least it comes back.
	 * And sometimes there is no keyboard...
	 *
	 * The reset register (0xcf9) is usually in one of the bridge
	 * chips. The actual location and sequence could be extracted from
	 * ACPI but why bother, this is the end of the line anyway.
	 */
	print("no kbd; trying bios warm boot...");
	*(ushort*)KADDR(0x472) = 0x1234;	/* BIOS warm-boot flag */
	outb(0xCF9, 0x02);
	outb(0xCF9, 0x06);

	print("can't reset\n");
	for(;;)
		idle();
}
Пример #15
0
void
pageunchain(Page *p)
{
	if(canlock(&palloc))
		panic("pageunchain (palloc %p)", &palloc);
	if(p->prev)
		p->prev->next = p->next;
	else
		palloc.head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;
	p->prev = p->next = nil;
	palloc.freecount--;
}
Пример #16
0
void
addwaitstat(uintptr_t pc, uint64_t t0, int type)
{
	uint i;
	uint64_t w;

	if(waitstats.on == 0)
		return;

	cycles(&w);
	w -= t0;
	mfence();
	for(i = 0; i < NWstats; i++)
		if(waitstats.pcs[i] == pc){
			ainc(&waitstats.ns[i]);
			if(w > waitstats.wait[i])
				waitstats.wait[i] = w;	/* race but ok */
			waitstats.total[i] += w;		/* race but ok */
			return;
		}
	if(!canlock(&waitstatslk))
		return;

	for(i = 0; i < NWstats; i++)
		if(waitstats.pcs[i] == pc){
			ainc(&waitstats.ns[i]);
			if(w > waitstats.wait[i])
				waitstats.wait[i] = w;	/* race but ok */
			waitstats.total[i] += w;
			unlock(&waitstatslk);
			return;
		}

	for(i = 0; i < NWstats; i++)
		if(waitstats.pcs[i] == 0){
			waitstats.ns[i] = 1;
			waitstats.type[i] = type;
			waitstats.wait[i] = w;
			waitstats.total[i] = w;
			mfence();
			waitstats.pcs[i] = pc;
			waitstats.npcs++;
			break;
		}

	unlock(&waitstatslk);
}
Пример #17
0
Файл: clock.c Проект: 8l/inferno
static void
clockintr(Ureg*, void*)
{
	Clock0link *lp;

	m->ticks++;

	checkalarms();

	if(canlock(&clock0lock)){
		for(lp = clock0link; lp; lp = lp->link)
			if (lp->clock)
				lp->clock();
		unlock(&clock0lock);
	}
	intrclear(TIMERbit(0), 0);
}
Пример #18
0
void
qlock(QLock *q)
{
	Proc *up = externup();
	Proc *p;
	uint64_t t0;

	cycles(&t0);

	if(!islo() && machp()->ilockdepth != 0){
		print("qlock with ilockdepth %d,", machp()->ilockdepth);
		stacksnippet();
	}

	if(up != nil && up->nlocks)
		print("qlock: %#p: nlocks %d", getcallerpc(&q), up->nlocks);

	if(!canlock(&q->use)){
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	qlockstats.qlock++;
	if(!q->locked) {
		q->locked = 1;
		q->pc = getcallerpc(&q);
		unlock(&q->use);
		return;
	}
	if(up == nil)
		panic("qlock");
	qlockstats.qlockq++;
	p = q->tail;
	if(p == 0)
		q->head = up;
	else
		p->qnext = up;
	q->tail = up;
	up->qnext = 0;
	up->state = Queueing;
	up->qpc = getcallerpc(&q);
	if(up->trace)
		proctrace(up, SLock, 0);
	unlock(&q->use);
	sched();
	lockstat(getcallerpc(&q), t0);
}
Пример #19
0
void
pagechaintail(Page *p)
{
	if(canlock(&palloc))
		panic("pagechaintail");
	if(palloc.tail) {
		p->prev = palloc.tail;
		palloc.tail->next = p;
	}
	else {
		palloc.head = p;
		p->prev = 0;
	}
	palloc.tail = p;
	p->next = 0;
	palloc.freecount++;
}
Пример #20
0
void
pageunchain(Page *p)
{
	Pgsza *pa;

	if(canlock(&pga.l))
		panic("pageunchain");
	pa = &pga.pgsza[p->pgszi];
	if(p->prev)
		p->prev->next = p->next;
	else
		pa->head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		pa->tail = p->prev;
	p->prev = p->next = nil;
	pa->freecount--;
}
Пример #21
0
Файл: proc.c Проект: npe9/harvey
/*
 *  try to remove a process from a scheduling queue (called splhi)
 */
Proc*
dequeueproc(Sched *sch, Schedq *rq, Proc *tp)
{
	Proc *l, *p;

	if(!canlock(sch))
		return nil;

	/*
	 *  the queue may have changed before we locked runq,
	 *  refind the target process.
	 */
	l = 0;
	for(p = rq->head; p; p = p->rnext){
		if(p == tp)
			break;
		l = p;
	}

	/*
	 *  p->mach==0 only when process state is saved
	 */

	if(p == 0 || p->mach){
		unlock(sch);
		return nil;
	}
	if(p->rnext == 0)
		rq->tail = l;
	if(l)
		l->rnext = p->rnext;
	else
		rq->head = p->rnext;
	if(rq->head == nil)
		sch->runvec &= ~(1<<(rq-sch->runq));
	rq->n--;
	sch->nrdy--;
	if(p->state != Ready)
		print("dequeueproc %s %d %s\n", p->text, p->pid, statename[p->state]);

	unlock(sch);
	return p;
}
Пример #22
0
void
wunlock(RWlock *q)
{
	Proc *p;
	uint64_t t0;

	if(!canlock(&q->use)){
		cycles(&t0);
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	p = q->head;
	if(p == nil){
		q->writer = 0;
		unlock(&q->use);
		return;
	}
	if(p->state == QueueingW){
		/* start waiting writer */
		q->head = p->qnext;
		if(q->head == nil)
			q->tail = nil;
		unlock(&q->use);
		ready(p);
		return;
	}

	if(p->state != QueueingR)
		panic("wunlock");

	/* waken waiting readers */
	while(q->head != nil && q->head->state == QueueingR){
		p = q->head;
		q->head = p->qnext;
		q->readers++;
		ready(p);
	}
	if(q->head == nil)
		q->tail = nil;
	q->writer = 0;
	unlock(&q->use);
}
Пример #23
0
/* same as rlock but punts if there are any writers waiting */
int
canrlock(RWlock *q)
{
	uint64_t t0;

	if(!canlock(&q->use)){
		cycles(&t0);
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	qlockstats.rlock++;
	if(q->writer == 0 && q->head == nil){
		/* no writer, go for it */
		q->readers++;
		unlock(&q->use);
		return 1;
	}
	unlock(&q->use);
	return 0;
}
Пример #24
0
void
pagechainhead(Page *p)
{
	Pgsza *pa;

	if(canlock(&pga.l))
		panic("pagechainhead");
	pa = &pga.pgsza[p->pgszi];
	if(pa->head) {
		p->next = pa->head;
		pa->head->prev = p;
	}
	else {
		pa->tail = p;
		p->next = 0;
	}
	pa->head = p;
	p->prev = 0;
	pa->freecount++;
}
Пример #25
0
Файл: vga.c Проект: 8l/inferno
static void
vgascreenputs(char* s, int n)
{
	int i;
	Rune r;
	char buf[4];
	VGAscr *scr;
	Rectangle flushr;

	scr = &vgascreen[0];

	if(!islo()){
		/*
		 * Don't deadlock trying to
		 * print in an interrupt.
		 */
		if(!canlock(&vgascreenlock))
			return;
	}
	else
		lock(&vgascreenlock);

	flushr = Rect(10000, 10000, -10000, -10000);

	while(n > 0){
		i = chartorune(&r, s);
		if(i == 0){
			s++;
			--n;
			continue;
		}
		memmove(buf, s, i);
		buf[i] = 0;
		n -= i;
		s += i;
		vgascreenputc(scr, buf, &flushr);
	}
	flushmemscreen(flushr);

	unlock(&vgascreenlock);
}
Пример #26
0
Файл: mp.c Проект: 8l/inferno
void
mpshutdown(void)
{
	/*
	 * To be done...
	 */
	if(!canlock(&mpshutdownlock)){
		/*
		 * If this processor received the CTRL-ALT-DEL from
		 * the keyboard, acknowledge it. Send an INIT to self.
		 */
#ifdef FIXTHIS
		if(lapicisr(VectorKBD))
			lapiceoi(VectorKBD);
#endif /* FIX THIS */
		idle();
	}

	print("apshutdown: active = 0x%2.2uX\n", active.machs);
	delay(1000);
	splhi();

	/*
	 * INIT all excluding self.
	 */
	lapicicrw(0, 0x000C0000|ApicINIT);

#ifdef notdef
	/*
	 * Often the BIOS hangs during restart if a conventional 8042
	 * warm-boot sequence is tried. The following is Intel specific and
	 * seems to perform a cold-boot, but at least it comes back.
	 */
	*(ushort*)KADDR(0x472) = 0x1234;	/* BIOS warm-boot flag */
	outb(0xCF9, 0x02);
	outb(0xCF9, 0x06);
#else
	pcireset();
	i8042reset();
#endif /* notdef */
}
Пример #27
0
static void
dofreestacks(void)
{
	Stackfree *sf, *last, *next;

	if(stackfree==nil || !canlock(&stacklock))
		return;

	for(last=nil,sf=stackfree; sf; last=sf,sf=next){
		next = sf->next;
		if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
			free(sf);
			if(last)
				last->next = next;
			else
				stackfree = next;
			sf = last;
		}
	}
	unlock(&stacklock);
}
Пример #28
0
void
wlock(RWlock *q)
{
	Proc *up = externup();
	Proc *p;
	uint64_t t0;

	cycles(&t0);
	if(!canlock(&q->use)){
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	qlockstats.wlock++;
	if(q->readers == 0 && q->writer == 0){
		/* noone waiting, go for it */
		q->wpc = getcallerpc(&q);
		q->wproc = up;
		q->writer = 1;
		unlock(&q->use);
		return;
	}

	/* wait */
	qlockstats.wlockq++;
	p = q->tail;
	if(up == nil)
		panic("wlock");
	if(p == nil)
		q->head = up;
	else
		p->qnext = up;
	q->tail = up;
	up->qnext = 0;
	up->state = QueueingW;
	if(up->trace)
		proctrace(up, SLock, 0);
	unlock(&q->use);
	sched();
	lockstat(getcallerpc(&q), t0);
}
Пример #29
0
void
threadexitsall(char *msg)
{
	static int pid[1024];
	int i, npid, mypid;
	Proc *p;

	if(msg == nil)
		msg = "";

	/* 
	 * Only one guy, ever, gets to run this.
	 * If two guys do it, inevitably they end up
	 * tripping over each other in the underlying
	 * C library exit() implementation, which is
	 * trying to run the atexit handlers and apparently
	 * not thread safe.  This has been observed on
	 * both Linux and OpenBSD.  Sigh.
	 */
	{
		static Lock onelock;
		if(!canlock(&onelock))
			_exits(threadexitsmsg);
		threadexitsmsg = msg;
	}

	if(msg == nil)
		msg = "";
	mypid = getpid();
	lock(&_threadprocslock);
	threadexitsmsg = msg;
	npid = 0;
	for(p=_threadprocs; p; p=p->next)
		if(p->osprocid != mypid && p->osprocid >= 1)
			pid[npid++] = p->osprocid;
	for(i=0; i<npid; i++)
		kill(pid[i], SIGUSR2);
	unlock(&_threadprocslock);
	exits(msg);
}
Пример #30
0
void
machinit(void)
{
	Mach *m0;

	if (m == 0) {
		serialputc('?');
		serialputc('m');
		serialputc('0');
	}
	if(machaddr[m->machno] != m) {
		serialputc('?');
		serialputc('m');
		serialputc('m');
	}

	if (canlock(&testlock)) {
		serialputc('?');
		serialputc('l');
		panic("cpu%d: locks don't work", m->machno);
	}

	m->ticks = 1;
	m->perf.period = 1;
	m0 = MACHP(0);
	if (m->machno != 0) {
		/* synchronise with cpu 0 */
		m->ticks = m0->ticks;
		m->fastclock = m0->fastclock;
		m->cpuhz = m0->cpuhz;
		m->delayloop = m0->delayloop;
	}
	if (m->machno != 0 &&
	    (m->fastclock == 0 || m->cpuhz == 0 || m->delayloop == 0))
		panic("buggered cpu 0 Mach");

	machon(m->machno);
	fpoff();
}