🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: fj.mail-lists.parallel
Article #322

Re: Locks without using atomic instructions

#322
From: Bruce M. Walker
Date: Tue, 01 Sep 1992 13:42
121 lines
3391 bytes
In article <1992Aug31.124322.2555@hubcap.clemson.edu> iane@werple.pub.uu.oz.au (Ian Evans) writes:
> Let's say that there is a system (unfortunately there is) where some
> person (me) wants to get a few different computers communicating reliably,
> and the only available mechanism is reading a shared memory location, or
> writing a location, but there is no atomic set & test type instruction.
> It is possible, however, to get a unique system-wide process ID.

A working algorithm is described (in a Pascalish dialect) in "Operating
Systems Concepts", by Silberschatz et al.  I know it works because I've
tested it on an 8-cpu multiprocessor.

I translated it into C, and it's pretty small, so what the heck!
here it is ...

------ begin spinlock.c -----
/*
 * spinlock.c -- critical regions support
 *
 * This algorithm is from "Operating System Concepts, 2nd Ed., Peterson &
 * Silberschatz; Addison Wesley"; chapter 9, Algorithm 5.
 * Algorithm is due to Eisenberg and McGuire 1972.
 */

/*
 * Instructions:
 *
 * Define a spin-lock structure with the macro DEF_SPIN().
 * Lock a critical region by calling lock() and passing the address
 *  of a spin-lock structure to it.
 * Un-lock the critical region by calling unlock() with the same address.
 *
 * You must supply a routine my_proc_id() that yields a system-wide unique
 * integer identifier for each cpu, and a value for the macro MAX_CPU.
 *
 * Example:
 *
 *   DEF_SPIN(lck)
 *
 *   one_at_a_time()
 *   {
 *       lock(&lck);
 *       ...
 *       unlock(&lck);
 *   }
 */

#include "spinlock.h"

/*
 * attempt to lock a critical region; spin until successful.
 */
void
lock(SPIN *c)
{
	register int j, i = my_proc_id();

	for (;;) {
		c->flag[i] = WANT_IN;
		j = c->turn;
		while (j != i)
			if (c->flag[j] != IDLE)
				j = c->turn;
			else
				j = (j+1) % MAX_CPU;
		for (c->flag[i] = IN_CS;
		     j < MAX_CPU && (j == i || c->flag[j] != IN_CS);
		     j++)
			; /* empty */
		if (j >= MAX_CPU && (c->turn == i || c->flag[c->turn] == IDLE))
			break;
	}
	c->turn = i;
}

/*
 * unlock a critical region.
 */
void
unlock(SPIN *c)
{
	int j = (c->turn+1) % MAX_CPU;
	while (c->flag[j] == IDLE)
		j = (j+1) % MAX_CPU;
	c->turn = j;
	c->flag[my_proc_id()] = IDLE;
}
------ end spinlock.c -----

------ begin spinlock.h -----
/*
 * spinlock.h -- critical regions def'ns
 */

#ifndef _SPINLOCK_H_
#define _SPINLOCK_H_

typedef struct {
	int turn;
	int flag[MAX_CPU];
} SPIN;

/* flags */
#define IDLE	0
#define WANT_IN	1
#define IN_CS	2

#define DEF_SPIN(x)	SPIN x = {0}	/* initialize whole thing to zero */

/* critical.c */
void lock(SPIN *c);
void unlock(SPIN *c);

#endif /* _SPINLOCK_H_ */
------ end spinlock.h -----

ObEnjoy: Enjoy!

--
"The path of my life is strewn with cowpats from the devils' own herd."
                                          -- Edmund Blackadder II
bmw@isgtec.com   [ ...!uunet.ca!isgtec!bmw ]  Bruce Walker
Technical Details
Message-ID: <314736@nttlab.ntt.JP>
Path: arc1-ca.pugleaf.net!sparky!uunet!sun-barr!sh.wide!wnoc-tyo-news!etl.go.jp!gama!lab!nttlab!daemon

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!sun-barr!sh.wide!wnoc-tyo-news!etl.go.jp!gama!lab!nttlab!daemon
From: bmw@isgtec.com (Bruce M. Walker)
Newsgroups: fj.mail-lists.parallel
Subject: Re: Locks without using atomic instructions
Message-ID: <314736@nttlab.ntt.JP>
Date: 1 Sep 92 13:42:55 GMT
Sender: daemon@nttlab.ntt.JP
Distribution: fj
Lines: 121
Approved: news@nttlab.ntt