Subject: SMP API things, lock debugging, etc.
To: None <tech-smp@netbsd.org>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-smp
Date: 07/27/1999 00:57:57
Attached below are my thoughts for some MI APIs for handling SMP things.

Also, I've almost finished implementing full blown LOCKDEBUG for the
MULTIPROCESSOR case as well.

        -- Jason R. Thorpe <thorpej@nas.nasa.gov>

The following is to propose some basic API components necessary
for multiprocessor support in the NetBSD kernel.

IMPORTANT NOTE
--------------

Some people have suggested that a data type `cpuid_t' be introduced to
hold CPU identifiers.  After some consideration, I have concluded that
the type `unsigned long' is preferable for the following reasons:

	Machine-independent code may wish to print out the value of
	a CPU identifier.  Therefore a type with a well-defined printf
	format should be used.

	The `unsigned long' type is the size of a register on all current
	ILP32 and LP64 platforms supported by NetBSD.  Therefore, this
	type is safe to use for this purpose on all platforms.



HEADER FILES
------------

API components will be defined in <machine/cpu.h> and by <machine/lock.h>.
The <machine/lock.h> header will be included by <sys/lock.h> only if the
CPP symbol MULTIPROCESSOR is defined.


FUNCTIONS AND MACROS
--------------------

The following functions or macros will be exported by <machine/cpu.h>:

	u_long cpu_number(void);

		MANDATORY

		This function, inline function, or macro returns the
		CPU identifier of the currently-running CPU.  If the
		system does not support multiple processors, or the
		kernel is built without support for multiple processors,
		this value should return a constant, unspecified value.


The following functions or macros will be exported by <machine/lock.h>:

	void cpu_simple_lock_init(__volatile struct simplelock *alp);

		MANDATORY

		This function, inline function, or macro initializes
		the `lock_data' member of `struct simplelock' to the
		value 0.

	void cpu_simple_lock(__volatile struct simplelock *alp);

		MANDATORY

		This function, inline function, or macro acquires
		the specified simple lock by performing the following
		operations in an atomic manner:

			while (alp->lock_data != 0) /* spin */;
			alp->lock_data = 1;

	int cpu_simple_lock_try(__volatile struct simplelock *alp);

		MANDATORY

		This function, inline function, or macro attempts to
		acquire the specified simple lock by performing the
		following operations in an atomic manner:

			if (alp->lock_data != 0)
				return (0);
			else {
				alp->lock_data = 1;
				return (1);
			}

	void cpu_simple_unlock(__volatile struct simplelock *alp);

		MANDATORY

		This function, inline function, or macro releases
		a previously acquired simple lock by performing
		the following operation:

			alp->lock_data = 0;


DATA STRUCTURES
---------------

The following data structures will be exported by <machine/cpu.h>:

	struct cpu_info;

		only if MULTIPROCESSOR

		This structure will always export the following members:

		- struct proc *ci_curproc: current process on this processor

		- struct simplelock ci_slock: simple lock for cpu_info
		  structure.  Note that use of this lock must remain
		  untracked in the case of lock debugging.  While this
		  lock is held, all interrupts MUST be blocked, as this
		  lock may be asserted from an interrupt context.

		- u_long ci_cpuid: CPU identifier of associated CPU

		This structure will export the following members if
		the DIAGNOSTIC or LOCKDEBUG CPP symbols are defined:

		- u_long ci_spin_locks: number of spin locks held by
		  this processor

		- u_long ci_simple_locks: number of simple locks held
		  by this processor

		This structure will export the following members if
		the LOCKDEBG CPP symbol is defined:

		- struct spinlock_list ci_spin_lock_list: TAILQ of
		  spin locks held by this processor

		- struct simplelock_list ci_simple_lock_list: TAILQ of
		  simple locks held by this processor

	extern struct cpu_info cpu_info[];

		only if MULTIPROCESSOR

		This is an array of cpu_info structures declared and allocated
		in a machine-dependent source file.  It must be allocated
		and initialized before any machine-independent code is
		executed during the bootstrap process.  This array will
		be indexed by the value returned by the `cpu_number()'
		function.

		cpu_info[] will be referenced in <sys/proc.h> by the
		following code block:

#if defined(MULTIPROCESSOR)
#define	curproc		cpu_info[cpu_number()].ci_curproc
#else
extern struct proc	*curproc;
#endif