Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/power/lock.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname power/lock.c 1990/0227
## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/lock.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"

/*
 * The hardware semaphores are strange.  64 per page, replicated 16 times
 * per page, 1024 pages of them.  Only the low bit is meaningful.
 * Reading an unset semaphore sets the semaphore and returns the old value.
 * Writing a semaphore sets the value, so writing 0 resets (clears) the semaphore.
 */

#define	SEMPERPG	64		/* hardware semaphores per page */
#define	NONSEMPERPG	(WD2PG-64)	/* words of non-semaphore per page */

struct
{
	Lock	lock;			/* lock to allocate */
	ulong	*nextsem;		/* next one to allocate */
	int	nsem;			/* at SEMPERPG, jump to next page */
}semalloc;

void
lockinit(void)
{
	semalloc.lock.sbsem = SBSEM;
	semalloc.nextsem = SBSEM+1;
	semalloc.nsem = 1;
	unlock(&semalloc.lock);
}

/*
 * If l->sbsem is zero, allocate a hardware semaphore first.
 * There is no way to free a semaphore.
 */
void
lock(Lock *l)
{
int addr;
	int i;
	ulong *sbsem;

	sbsem = l->sbsem;
	if(sbsem == 0){
		lock(&semalloc.lock);
		if(semalloc.nsem == SEMPERPG){
			semalloc.nsem = 0;
			semalloc.nextsem += NONSEMPERPG;
			if(semalloc.nextsem == SBSEMTOP)
				panic("sem");
		}
		l->sbsem = semalloc.nextsem;
		semalloc.nextsem++;
		semalloc.nsem++;
		unlock(&semalloc.lock);
		unlock(l);		/* put sem in known state */
		sbsem = l->sbsem;
	}
	/*
	 * Try the fast grab first
	 */
    	if((*sbsem&1) == 0){
		l->pc = ((ulong*)&addr)[-7];
		return;
	}
	for(i=0; i<10000000; i++)
    		if((*sbsem&1) == 0){
			l->pc = ((ulong*)&addr)[-7];
			return;
	}
	*sbsem = 0;
	print("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&addr)[-7], l->pc);
}

int
canlock(Lock *l)
{
	ulong *sbsem;

	sbsem = l->sbsem;
	if(sbsem == 0){
		lock(&semalloc.lock);
		if(semalloc.nsem == SEMPERPG){
			semalloc.nsem = 0;
			semalloc.nextsem += NONSEMPERPG;
			if(semalloc.nextsem == SBSEMTOP)
				panic("sem");
		}
		l->sbsem = semalloc.nextsem;
		semalloc.nextsem++;
		semalloc.nsem++;
		unlock(&semalloc.lock);
		unlock(l);		/* put sem in known state */
		sbsem = l->sbsem;
	}
	if(*sbsem & 1)
		return 0;
	return 1;
}

void
unlock(Lock *l)
{
	l->pc = 0;
	*l->sbsem = 0;
}

int
canqlock(QLock *q)
{
	return canlock(&q->use);
}

void
qlock(QLock *q)
{
	Proc *p;

	if(canlock(&q->use))
		return;
	lock(&q->queue);
	if(canlock(&q->use)){
		unlock(&q->queue);
		return;
	}
	p = q->tail;
	if(p == 0)
		q->head = u->p;
	else
		p->qnext = u->p;
	q->tail = u->p;
	u->p->qnext = 0;
	u->p->state = Queueing;
	unlock(&q->queue);
	sched();
}

void
qunlock(QLock *q)
{
	Proc *p;

	lock(&q->queue);
	if(q->head){
		p = q->head;
		q->head = p->qnext;
		if(q->head == 0)
			q->tail = 0;
		unlock(&q->queue);
		ready(p);
	}else{
		unlock(&q->use);
		unlock(&q->queue);
	}
}
.
## diffname power/lock.c 1990/0322
## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/lock.c /n/bootesdump/1990/0322/sys/src/9/mips/lock.c
154,155c
		q->locked = 0;
		unlock(q);
.
151c
		unlock(q);
.
145,147c
	lock(q);
	p = q->head;
	if(p){
.
136c
	unlock(q);
.
123,126d
121c
	lock(q);
	if(!q->locked){
		q->locked = 1;
		unlock(q);
.
113c
	lock(q);
	if(q->locked){
		unlock(q);
		return 0;
	}
	q->locked = 1;
	unlock(q);
	return 1;
.
## diffname power/lock.c 1990/0324
## diff -e /n/bootesdump/1990/0322/sys/src/9/mips/lock.c /n/bootesdump/1990/0324/sys/src/9/mips/lock.c
160,161c
		unlock(&q->use);
		unlock(&q->queue);
.
157c
		unlock(&q->queue);
.
151,153c
	lock(&q->queue);
	if(q->head){
		p = q->head;
.
142c
	unlock(&q->queue);
.
132a
	lock(&q->queue);
	if(canlock(&q->use)){
		unlock(&q->queue);
		return;
.
128,131c
	if(canlock(&q->use))
.
113,120c
	return canlock(&q->use);
.
## diffname power/lock.c 1990/1115
## diff -e /n/bootesdump/1990/0324/sys/src/9/mips/lock.c /n/bootesdump/1990/1115/sys/src/9/mips/lock.c
74a
dumpstack();
.
## diffname power/lock.c 1990/1214
## diff -e /n/bootesdump/1990/1115/sys/src/9/mips/lock.c /n/bootesdump/1990/1214/sys/src/9/mips/lock.c
74c
	print("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&ll)[PCOFF], l->pc);
.
70c
			l->pc = ((ulong*)&ll)[PCOFF];
.
64,65c
	if((*sbsem&1) == 0){
		l->pc = ((ulong*)&ll)[PCOFF];
.
41c
	Lock *l = ll;
.
39c
lock(Lock *ll)
.
33a
#define PCOFF -9

.
## diffname power/lock.c 1991/0428
## diff -e /n/bootesdump/1991/0201/sys/src/9/mips/lock.c /n/bootesdump/1991/0428/sys/src/9/power/lock.c
112,160d
## diffname power/lock.c 1991/0605
## diff -e /n/bootesdump/1991/0428/sys/src/9/power/lock.c /n/bootesdump/1991/0605/sys/src/9/power/lock.c
90,92c
			semalloc.nextsem = lkpgalloc();
.
77c
	dumpstack();
.
52,54c
			semalloc.nextsem = lkpgalloc();
.
38d
33a
/* return the address of the next free page of locks */
ulong*
lkpgalloc(void)
{
	uchar *p, *top;

	top = &semalloc.bmap[NSEMPG];
	for(p = semalloc.bmap; *p && p < top; p++)
		;
	if(p == top)
		panic("lkpgalloc");

	*p = 1;
	return (p-semalloc.bmap)*WD2PG + SBSEM;
}

void
lkpgfree(ulong *lpa)
{
	uchar *p;

	p = &semalloc.bmap[(lpa-SBSEM)/WD2PG];
	if(!*p)
		panic("lkpgfree");
	*p = 0;
}

.
27a
	memset(semalloc.bmap, 0, sizeof(semalloc.bmap));
	semalloc.bmap[0] = 1;
.
22a
	uchar	bmap[NSEMPG];		/* allocation map */
.
16c
#define NSEMPG		1024
.
## diffname power/lock.c 1991/0606
## diff -e /n/bootesdump/1991/0605/sys/src/9/power/lock.c /n/bootesdump/1991/0606/sys/src/9/power/lock.c
135a
}

void
mklockseg(Seg *s)
{
	Orig *o;

	s->proc = u->p;
	o = neworig(LKSEGBASE, 0, OWRPERM|OPURE, 0);
	o->minca = 0;
	o->maxca = 0;
	s->o = o;
	s->minva = LKSEGBASE;
	s->maxva = LKSEGBASE;
	s->mod = 0;
.
52a
/* Moral equivalent of newpage for pages of hardware lock */
Page*
lkpage(Orig *o, ulong va)
{
	uchar *p, *top;
	Page *pg;
	int i;

	lock(&semalloc.lock);
	top = &semalloc.bmap[NSEMPG];
	for(p = semalloc.bmap; *p && p < top; p++)
		;
	if(p == top)
		panic("lkpage");

	*p = 1;
	i = p-semalloc.bmap;
	pg = &lkpgheader[i];
	pg->pa = (ulong)((i*WD2PG) + SBSEM);
	pg->va = va;
	pg->o = o;

	unlock(&semalloc.lock);
	return pg;
}

.
30a

.
25a
Page lkpgheader[NSEMPG];

.
6a
#include "errno.h"
.
## diffname power/lock.c 1991/0607
## diff -e /n/bootesdump/1991/0606/sys/src/9/power/lock.c /n/bootesdump/1991/0607/sys/src/9/power/lock.c
176a
	o->freepg = lkpgfree;
.
174c
	o = neworig(LKSEGBASE, 0, OWRPERM|OSHARED, 0);
.
91a
	
	semalloc.ulockpg++;
	unlock(&semalloc.lock);
.
88c
	lock(&semalloc.lock);
	p = &semalloc.bmap[((pg->pa|UNCACHED)-(ulong)SBSEM)/BY2PG];
.
84c
lkpgfree(Page *pg, int dolock)
.
77a
	pg->ref = 1;
.
75c
	pg->pa = (ulong)((i*WD2PG) + SBSEM) & ~UNCACHED;
.
65a
	if(--semalloc.ulockpg < 0) {
		semalloc.ulockpg++;
		unlock(&semalloc.lock);
		return 0;
	}
.
34a
	semalloc.ulockpg = ULOCKPG;
.
24a
	int	ulockpg;		/* count of user lock available */
.
17a
#define ULOCKPG		512
.
## diffname power/lock.c 1991/0614
## diff -e /n/bootesdump/1991/0607/sys/src/9/power/lock.c /n/bootesdump/1991/0614/sys/src/9/power/lock.c
178a
	if(u && u->p)
		u->p->hasspin = 0;
.
170a
	if(u && u->p)
		u->p->hasspin = 1;
.
142a
			if(u && u->p)
				u->p->hasspin = 1;
.
137a
		if(u && u->p)
			u->p->hasspin = 1;
.
## diffname power/lock.c 1991/0705
## diff -e /n/bootesdump/1991/0614/sys/src/9/power/lock.c /n/bootesdump/1991/0705/sys/src/9/power/lock.c
185,202d
175,176d
145,146d
138,139d
93c
lkpgfree(Page *pg)
.
85d
62c
lkpage(ulong va)
.
## diffname power/lock.c 1991/0726
## diff -e /n/bootesdump/1991/0705/sys/src/9/power/lock.c /n/bootesdump/1991/0726/sys/src/9/power/lock.c
169a
	l->pc = getcallerpc();
.
145c
	print("lock loop %lux pc %lux held by pc %lux\n", l, getcallerpc(), l->pc);
.
141c
			l->pc = getcallerpc();
.
136c
		l->pc = getcallerpc();
.
114d
112c
lock(Lock *l)
.
106,107d
## diffname power/lock.c 1991/0802
## diff -e /n/bootesdump/1991/0726/sys/src/9/power/lock.c /n/bootesdump/1991/0802/sys/src/9/power/lock.c
162d
158,160d
154,156c
		if(l->sbsem == 0){
			if(semalloc.nsem == SEMPERPG){
				semalloc.nsem = 0;
				semalloc.nextsem = lkpgalloc();
			}
			l->sbsem = semalloc.nextsem;
			semalloc.nextsem++;
			semalloc.nsem++;
			unlock(l);		/* put sem in known state */
.
126d
122,124d
118,120c
		if(l->sbsem == 0){
			if(semalloc.nsem == SEMPERPG){
				semalloc.nsem = 0;
				semalloc.nextsem = lkpgalloc();
			}
			l->sbsem = semalloc.nextsem;
			semalloc.nextsem++;
			semalloc.nsem++;
			unlock(l);		/* put sem in known state */
.
## diffname power/lock.c 1992/0111
## diff -e /n/bootesdump/1991/0802/sys/src/9/power/lock.c /n/bootesdump/1992/0111/sys/src/9/power/lock.c
7c
#include "../port/error.h"
.
## diffname power/lock.c 1992/0222
## diff -e /n/bootesdump/1992/0111/sys/src/9/power/lock.c /n/bootesdump/1992/0222/sys/src/9/power/lock.c
171c
	l->pc = getcallerpc(l);
.
144c
	print("lock loop %lux pc %lux held by pc %lux\n", l, getcallerpc(l), l->pc);
.
140c
			l->pc = getcallerpc(l);
.
135c
		l->pc = getcallerpc(l);
.
## diffname power/lock.c 1992/0321
## diff -e /n/bootesdump/1992/0222/sys/src/9/power/lock.c /n/bootesdump/1992/0321/sys/src/9/power/lock.c
2c
#include "../port/lib.h"
.
## diffname power/lock.c 1992/0622
## diff -e /n/bootesdump/1992/0321/sys/src/9/power/lock.c /n/bootesdump/1992/0622/sys/src/9/power/lock.c
179c
	l->val = 0;
.
169,172d
166,167c
		if(lk->val)
			return 0;
.
161,164d
153,159c
	hash = lhash(lk);
	hwsem = (int*)SBSEM+hash;

	for(;;) {
		if((*hwsem & 1) == 0) {
			if(lk->val)
				*hwsem = 0;
			else {
				lk->val = 1;
				*hwsem = 0;
				lk->pc = getcallerpc(lk);
				return 1;
.
151c
	int *hwsem;
	int i, hash;
.
149c
canlock(Lock *lk)
.
146c
}	
.
131,144c
	print("lock loop %lux pc %lux held by pc %lux\n", lk, getcallerpc(lk), lk->pc);
.
128,129c
		while(lk->val && i)
			i--;
		if(i <= 0)
			break;
.
123,126d
115,121c
	hash = lhash(lk);
	hwsem = (int*)SBSEM+hash;

	i = 1000000;
	for(;;) {
		if((*hwsem & 1) == 0) {
			if(lk->val)
				*hwsem = 0;
			else {
				lk->val = 1;
				*hwsem = 0;
				lk->pc = getcallerpc(lk);
				return;
.
112,113c
	int *hwsem;
	int i, hash;
.
110c
lock(Lock *lk)
.
106,108d
44,60c
/* Moral equivalent of newpage for pages of hardware locks */
.
38,41d
35,36c
	/*
	 * Initialise the system semaphore hardware
	 */
	memset(SBSEM, 0, (NSEMPG-ULOCKPG)*BY2PG);
.
29a
#define lhash(laddr)	((int)laddr>>2)&(((NSEMPG-ULOCKPG)*(BY2PG>>2))-1)
.
23,24d
16,18c
enum
{
	SEMPERPG	= 64,		/* hardware semaphores per page */
	NSEMPG		= 1024,
	ULOCKPG		= 512,
};
.
## diffname power/lock.c 1992/0629
## diff -e /n/bootesdump/1992/0622/sys/src/9/power/lock.c /n/bootesdump/1992/0629/sys/src/9/power/lock.c
127,142c
	return muxlock((int*)SBSEM+hash, &lk->val);
.
123,124c
	int hash;
.
101,114c
		if(muxlock(hwsem, &lk->val))
			return;
		while(lk->val)
			;
.
99d
93,94c
	int *hwsem, hash;
.
61c
	if(p >= top)
.
59c
	for(p = semalloc.bmap; p < top && *p; p++)
.
44c
/* equivalent of newpage for pages of hardware locks */
.
40c
	for(i = 0; i < (NSEMPG-ULOCKPG)*BY2PG; i += 4) {
		h = lhash(i);
		sbsem = (int*)SBSEM+h;
		*sbsem = 0;
	}
.
36c
	int *sbsem, h, i;

.
31c
#define lhash(laddr)	((int)laddr>>2)&(((NSEMPG-ULOCKPG)*(BY2PG>>2))-1)&~0x3c0
.
10,11c
 * The hardware semaphores are strange.  Only 64 per page can be used,
 * 1024 pages of them.  Only the low bit is meaningful.
.
## diffname power/lock.c 1993/0120
## diff -e /n/bootesdump/1992/0629/sys/src/9/power/lock.c /n/bootesdump/1993/0120/sys/src/9/power/lock.c
56a
	USED(s);
.
51c
lkpage(Segment *s, ulong va)
.
## diffname power/lock.c 1993/0501
## diff -e /n/bootesdump/1993/0120/sys/src/9/power/lock.c /n/fornaxdump/1993/0501/sys/src/brazil/power/lock.c
55a
	Page *pg;
	uchar *p, *top;
.
53,54d
## diffname power/lock.c 1994/0218
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/power/lock.c /n/fornaxdump/1994/0218/sys/src/brazil/power/lock.c
73c
	pa = (ulong)(SBSEM+(i*WD2PG));
	memset((void*)pa, 0, BY2PG);
	pg->pa = pa & ~UNCACHED;
.
55a
	ulong pa;
.
## diffname power/lock.c 1994/0405
## diff -e /n/fornaxdump/1994/0218/sys/src/brazil/power/lock.c /n/fornaxdump/1994/0405/sys/src/brazil/power/lock.c
130a
}

void
iunlock(Lock *l)
{
	ulong sr;

	sr = l->sr;
	l->pc = 0;
	l->val = 0;
	splx(sr);
.
116a
void
ilock(Lock *lk)
{
	int *hwsem, hash;
	ulong x;

	x = splhi();
	hash = lhash(lk);
	hwsem = (int*)SBSEM+hash;

	for(;;) {
		if(muxlock(hwsem, &lk->val)){
			lk->sr = x;
			return;
		}
		while(lk->val)
			;
	}
	splx(x);
	print("lock loop %lux pc %lux held by pc %lux\n", lk, getcallerpc(lk), lk->pc);
	dumpstack();
}	

.
## diffname power/lock.c 1997/0327 # deleted
## diff -e /n/fornaxdump/1994/0405/sys/src/brazil/power/lock.c /n/emeliedump/1997/0327/sys/src/brazil/power/lock.c
1,165d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].