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