1: /*
   2:  * Rewritten for 2.11BSD. Feb 20 1995, Steven Schultz (sms@wlv.iipo.gtegsc.com)
   3:  *
   4:  * The lock table is allocated external to the kernel (in pdp/machdep2.c at
   5:  * kernel startup time) because 8 concurrent Ingres sessions would have cost
   6:  * over 500 bytes of D space.
   7:  */
   8: 
   9: #include    "ingres.h"
  10: #if NINGRES > 0
  11: 
  12: #include    "param.h"
  13: #include    <sys/file.h>
  14: #include    <sys/user.h>
  15: #include    <sys/proc.h>
  16: #include    <sys/uio.h>
  17: #include    <machine/seg.h>
  18: #include    <sys/ingreslock.h>
  19: 
  20: /*
  21:  * Wait channels for locktable.  We need something which is even, unique and
  22:  * not mapped out to sleep on when waiting for a lock.
  23: */
  24:     int Locksleep[IL_NLOCKS];
  25:     segm    Locktabseg;
  26:     struct  Lockform *Locktab = (struct Lockform *)SEG5;
  27: 
  28: /*
  29:  * array of number of locks which can be set for each lock.
  30:  * It looks tempting to make this an array of char or u_char.  DON'T.  The
  31:  * entries are used as wait channel addresses and must be 'even'.
  32: */
  33:     int Lockset[] =
  34:         {
  35:         IL_NLOCKS,
  36:         IL_PLOCKS,
  37:         IL_RLOCKS,
  38:         IL_DLOCKS
  39:         };
  40: 
  41: #define keycomp(a,b)    bcmp(a,b,KEYSIZE)
  42: 
  43: ingres_open(dev, flag, mode)
  44:     dev_t   dev;
  45:     int flag;
  46:     int mode;
  47:     {
  48: 
  49:     if  ((flag & FWRITE) == 0)
  50:         return(EBADF);
  51:     if  (Locktabseg.se_addr == 0)
  52:         return(ENOMEM);
  53:     return(0);
  54:     }
  55: 
  56: /*
  57:  *	ingres_write() : write driver
  58:  *		1. copy Lock request info to lockbuf
  59:  *		2. follow action in l_act
  60:  *		3. Error return conditions
  61:  *			-1: lockrequest fails(only on act=1)
  62:  *			-2: attempt to release a lock not set
  63:  *			    by calling program
  64:  *			-3: illegal action requested
  65:  *
  66:  *	Install the line "ingres_rma(p->p_pid)" in the routine
  67:  *	"exit" (in sys/kern_exit.c) after "p->p_stat = SZOMB".
  68: */
  69: 
  70: ingres_write(dev, uio, flag)
  71:     dev_t   dev;
  72:     struct  uio *uio;
  73:     int flag;
  74: {
  75:     struct Lockreq  lockbuf;
  76:     register struct Lockreq *ll;
  77:     register int    i;
  78:     int error = 0, blockflag;
  79: 
  80:     if  (uio->uio_resid != sizeof (struct ulock))
  81:         return(EINVAL);
  82:     error = uiomove(&lockbuf.lr_req, sizeof (struct ulock), uio);
  83:     if  (error)
  84:         return(error);
  85:     lockbuf.lr_pid = u.u_procp->p_pid;
  86:     ll = &lockbuf;
  87:     if  ((ll->lr_act < A_RLS1)
  88:            && ((ll->lr_type < T_CS) || (ll->lr_type > T_DB )
  89:            || (ll->lr_mod < M_EXCL) || (ll->lr_mod > M_SHARE )))
  90:         return(EINVAL);
  91: 
  92: /*
  93:  * At this point we are in the high kernel and do not need to save seg5
  94:  * before changing it.  Making sure that 'normalseg5' is called before doing
  95:  * a sleep() or return() is sufficient.
  96:  *
  97:  * It is simpler to map the lock table once here rather than in each routine
  98:  * called below.
  99: */
 100:     ingres_maplock();
 101: 
 102:     switch(ll->lr_act)
 103:     {
 104:       case A_RTN:
 105:                     /*
 106: 					 * attempt to set lock.
 107: 					 * error return if failure.
 108: 					 */
 109:         blockflag = FALSE;
 110:         for ( i = 0; i <= ll->lr_type; i++)
 111:             if (Lockset[i] == 0)
 112:                 blockflag = TRUE;
 113:         if (blockflag || ingres_unique(ll) >= 0)
 114:             error = -1;
 115:         else
 116:             ingres_enter(ll);
 117:         break;
 118: 
 119:       case A_SLP:
 120:                 /* attempt to set lock.
 121: 				 * sleep on blocking address if failure.
 122: 				 */
 123:         do
 124:         {
 125:             do
 126:             {
 127:                 blockflag = TRUE;
 128:                 for ( i = 0; i <= ll->lr_type; i++)
 129:                     if (Lockset[i] == 0)
 130:                         {
 131:                         normalseg5();
 132:                         sleep(&Lockset[i],LOCKPRI);
 133:                         ingres_maplock();
 134:                         blockflag = FALSE;
 135:                         }
 136:             }
 137:             while (!blockflag);
 138:             if (( i = ingres_unique(ll)) >= 0 )
 139:                 {
 140:                 blockflag = FALSE;
 141:                 Locktab[i].l_wflag = W_ON;
 142:                 normalseg5();
 143:                 sleep(&Locksleep[i],LOCKPRI);
 144:                 ingres_maplock();
 145:                 }
 146:         }
 147:         while (!blockflag);
 148:         ingres_enter(ll);
 149:         break;
 150: 
 151:       case A_RLS1:
 152:                 /* remove 1 lock */
 153:         if ((i = ingres_find(ll)) >= 0)
 154:             ingres_rm(i,ll->lr_pid);
 155:         else
 156:             error = -2;
 157:         break;
 158: 
 159:       case A_RLSA:
 160:                 /* remove all locks for this process id*/
 161:         ingres_rma(ll->lr_pid); /* does a normalseg5() */
 162:         break;
 163: 
 164:       case A_ABT:       /* abort all locks */
 165:         ingres_abt();
 166:         break;
 167: 
 168:       default :
 169:         error = -3;
 170:         break;
 171:     }
 172:     normalseg5();
 173:     return(error);
 174: }
 175: 
 176: /*
 177:  *	ingres_unique- check for match on key
 178:  *
 179:  *	return index of Locktab if match found
 180:  *	else return -1
 181:  */
 182: 
 183: static
 184: ingres_unique(q)
 185: register struct Lockreq *q;
 186: {
 187:     register int    k;
 188:     register struct Lockform    *p = Locktab;
 189: 
 190:     for (k = 0; k < IL_NLOCKS; k++, p++)
 191:         {
 192:         if  ((p->l_mod != M_EMTY)
 193:               && (keycomp(p->l_key,q->lr_key) == 0)
 194:               && (p->l_type == q->lr_type)
 195:               && ((p->l_mod == M_EXCL) || (q->lr_mod == M_EXCL)))
 196:             return(k);
 197:         }
 198:     return(-1);
 199: }
 200: 
 201: static
 202: ingres_find(q)
 203: register struct Lockreq *q;
 204:     {
 205:     register int    k;
 206:     register struct Lockform    *p = Locktab;
 207: 
 208:     for (k = 0; k < IL_NLOCKS; k++, p++)
 209:         {
 210:         if  ((p->l_mod != M_EMTY)
 211:               && (keycomp(p->l_key,q->lr_key) == 0)
 212:               && (p->l_type == q->lr_type)
 213:               && (p->l_pid == q->lr_pid))
 214:             return(k);
 215:         }
 216:     return(-1);
 217:     }
 218: 
 219: /*
 220:  *	remove the lth Lock
 221:  *		if the correct user is requesting the move.
 222:  */
 223: 
 224: static void
 225: ingres_rm(l,llpid)
 226:     int l, llpid;
 227:     {
 228:     register struct Lockform *a = &Locktab[l];
 229:     register int    k;
 230: 
 231:     if  (a->l_pid == llpid && a->l_mod != M_EMTY)
 232:         {
 233:         a->l_mod = M_EMTY;
 234:         a->l_pid = 0;
 235:         if  (a->l_wflag == W_ON)
 236:             {
 237:             a->l_wflag = W_OFF;
 238:             wakeup(&Locksleep[l]);
 239:             }
 240:         for (k = 0; k <= a->l_type; k++)
 241:             {
 242:             Lockset[k]++;
 243:             if  (Lockset[k] == 1)
 244:                 wakeup(&Lockset[k]);
 245:             }
 246:         }
 247:     }
 248: 
 249: /*
 250:  *	ingres_rma releases all locks for a given process id(pd).
 251: */
 252: 
 253: ingres_rma(pd)
 254:     int pd;
 255:     {
 256:     register int    i;
 257:     register struct Lockform *p = Locktab;
 258: /*
 259:  * Have to map the lock table because we can be called from kern_exit.c
 260:  * when a process exits.
 261: */
 262:     ingres_maplock();
 263: 
 264: /*
 265:  * Replicate the pid check here to avoid function calls.  If this process
 266:  * has no Ingres locks outstanding then we avoid IL_NLOCKS function calls
 267:  * and returns.
 268: */
 269:     for (i = 0; i < IL_NLOCKS; i++, p++)
 270:         {
 271:         if  (p->l_pid == pd && (p->l_mod != M_EMTY))
 272:             ingres_rm(i,pd);
 273:         }
 274:     normalseg5();
 275:     }
 276: 
 277: /*
 278:  *	enter Lockbuf in locktable
 279:  *	return position in Locktable
 280:  *	error return of -1
 281:  */
 282: 
 283: static
 284: ingres_enter(ll)
 285: struct Lockreq  *ll;
 286:     {
 287:     register int    k, l;
 288:     register struct Lockform    *p = Locktab;
 289: 
 290:     for (k = 0; k < IL_NLOCKS; k++, p++)
 291:         {
 292:         if  (p->l_mod == M_EMTY)
 293:             {
 294:             p->l_pid = ll->lr_pid;
 295:             p->l_type = ll->lr_type;
 296:             p->l_mod = ll->lr_mod;
 297:             bcopy(ll->lr_key, p->l_key, KEYSIZE);
 298:             for (l = 0; l <= ll->lr_type; l++)
 299:                 Lockset[l]--;
 300:             return(k);
 301:             }
 302:         }
 303:     return (-1);
 304:     }
 305: 
 306: /*
 307:  *	ingres_abt - abort all locks
 308:  */
 309: 
 310: static void
 311: ingres_abt()
 312:     {
 313:     register int    k;
 314: 
 315:     for (k = 0; k < IL_NLOCKS; k++)
 316:         wakeup( &Locktab[k] );
 317:     for (k = 0; k < 4; k++)
 318:         wakeup( &Lockset[k]);
 319:     bzero(Locktab, LOCKTABSIZE);
 320:     Lockset[0] = IL_NLOCKS;
 321:     Lockset[1] = IL_PLOCKS;
 322:     Lockset[2] = IL_RLOCKS;
 323:     Lockset[3] = IL_DLOCKS;
 324:     }
 325: #endif /* NINGRES > 0 */

Defined functions

ingres_abt defined in line 310; used 1 times
ingres_enter defined in line 283; used 2 times
ingres_find defined in line 201; used 1 times
ingres_open defined in line 43; never used
ingres_rm defined in line 224; used 2 times
ingres_rma defined in line 253; used 2 times
ingres_unique defined in line 183; used 2 times
ingres_write defined in line 70; never used

Defined variables

Lockset defined in line 33; used 12 times
Locksleep defined in line 24; used 2 times
Locktab defined in line 26; used 8 times
Locktabseg defined in line 25; used 1 times
  • in line 51

Defined macros

keycomp defined in line 41; used 2 times
Last modified: 1995-02-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 133
Valid CSS Valid XHTML 1.0 Strict