|
Packit Service |
a8c26c |
.fp 5 CW
|
|
Packit Service |
a8c26c |
.TH LIBASO 3
|
|
Packit Service |
a8c26c |
.SH NAME
|
|
Packit Service |
a8c26c |
\fBASO\fP \- Atomic Scalar Operations
|
|
Packit Service |
a8c26c |
.SH SYNOPSIS
|
|
Packit Service |
a8c26c |
.de Tp
|
|
Packit Service |
a8c26c |
.fl
|
|
Packit Service |
a8c26c |
.ne 2
|
|
Packit Service |
a8c26c |
.TP
|
|
Packit Service |
a8c26c |
..
|
|
Packit Service |
a8c26c |
.de Ss
|
|
Packit Service |
a8c26c |
.fl
|
|
Packit Service |
a8c26c |
.ne 2
|
|
Packit Service |
a8c26c |
.SS "\\$1"
|
|
Packit Service |
a8c26c |
..
|
|
Packit Service |
a8c26c |
.de Cs
|
|
Packit Service |
a8c26c |
.nf
|
|
Packit Service |
a8c26c |
.ft 5
|
|
Packit Service |
a8c26c |
..
|
|
Packit Service |
a8c26c |
.de Ce
|
|
Packit Service |
a8c26c |
.ft 1
|
|
Packit Service |
a8c26c |
.fi
|
|
Packit Service |
a8c26c |
..
|
|
Packit Service |
a8c26c |
.ta 1.0i 2.0i 3.0i 4.0i 5.0i
|
|
Packit Service |
a8c26c |
.Cs
|
|
Packit Service |
a8c26c |
#include <aso.h>
|
|
Packit Service |
a8c26c |
.Ce
|
|
Packit Service |
a8c26c |
.Ss "TYPES"
|
|
Packit Service |
a8c26c |
.Cs
|
|
Packit Service |
a8c26c |
typedef int (*Asoerror_f)(int, const char*);
|
|
Packit Service |
a8c26c |
typedef void* (*Asoinit_f)(void*, const char*);
|
|
Packit Service |
a8c26c |
typedef ssize_t (*Asolock_f)(void*, ssize_t, void volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef struct Asodisc_s
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
uint32_t version;
|
|
Packit Service |
a8c26c |
unsigned int hung;
|
|
Packit Service |
a8c26c |
Asoerror_f errorf;
|
|
Packit Service |
a8c26c |
} Asodisc_t;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef struct Asometh_s
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
const char* name;
|
|
Packit Service |
a8c26c |
int type;
|
|
Packit Service |
a8c26c |
Asoinit_f initf;
|
|
Packit Service |
a8c26c |
Asolock_f lockf;
|
|
Packit Service |
a8c26c |
const char* details;
|
|
Packit Service |
a8c26c |
} Asometh_t;
|
|
Packit Service |
a8c26c |
.Ce
|
|
Packit Service |
a8c26c |
.Ss "OPERATIONS"
|
|
Packit Service |
a8c26c |
.Cs
|
|
Packit Service |
a8c26c |
uint8_t asocas8(uint8_t volatile*, int, int);
|
|
Packit Service |
a8c26c |
uint8_t asoget8(uint8_t volatile*);
|
|
Packit Service |
a8c26c |
uint8_t asoinc8(uint8_t volatile*);
|
|
Packit Service |
a8c26c |
uint8_t asodec8(uint8_t volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
uint16_t asocas16(uint16_t volatile*, uint16_t, uint16_t);
|
|
Packit Service |
a8c26c |
uint16_t asoget16(uint16_t volatile*);
|
|
Packit Service |
a8c26c |
uint16_t asoinc16(uint16_t volatile*);
|
|
Packit Service |
a8c26c |
uint16_t asodec16(uint16_t volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
uint32_t asocas32(uint32_t volatile*, uint32_t, uint32_t);
|
|
Packit Service |
a8c26c |
uint32_t asoget32(uint32_t volatile*);
|
|
Packit Service |
a8c26c |
uint32_t asoinc32(uint32_t volatile*);
|
|
Packit Service |
a8c26c |
uint32_t asodec32(uint32_t volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
uint64_t asocas64(uint64_t volatile*, uint64_t, uint64_t);
|
|
Packit Service |
a8c26c |
uint64_t asoget64(uint64_t volatile*);
|
|
Packit Service |
a8c26c |
uint64_t asoinc64(uint64_t volatile*);
|
|
Packit Service |
a8c26c |
uint64_t asodec64(uint64_t volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
unsigned char asocaschar(unsigned char volatile*, int, int);
|
|
Packit Service |
a8c26c |
unsigned char asogetchar(unsigned char volatile*);
|
|
Packit Service |
a8c26c |
unsigned char asoincchar(unsigned char volatile*);
|
|
Packit Service |
a8c26c |
unsigned char asodecchar(unsigned char volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
unsigned short asocasshort(unsigned short volatile*, unsigned short, unsigned short);
|
|
Packit Service |
a8c26c |
unsigned short asogetshort(unsigned short volatile*);
|
|
Packit Service |
a8c26c |
unsigned short asoincshort(unsigned short volatile*);
|
|
Packit Service |
a8c26c |
unsigned short asodecshort(unsigned short volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
unsigned int asocasint(unsigned int volatile*, unsigned int, unsigned int);
|
|
Packit Service |
a8c26c |
unsigned int asogetint(unsigned int volatile*);
|
|
Packit Service |
a8c26c |
unsigned int asoincint(unsigned int volatile*);
|
|
Packit Service |
a8c26c |
unsigned int asodecint(unsigned int volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
unsigned long asocaslong(unsigned long volatile*, unsigned long, unsigned long);
|
|
Packit Service |
a8c26c |
unsigned long asogetlong(unsigned long volatile*);
|
|
Packit Service |
a8c26c |
unsigned long asoinclong(unsigned long volatile*);
|
|
Packit Service |
a8c26c |
unsigned long asodeclong(unsigned long volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
size_t asocassize(size_t volatile*, size_t, size_t);
|
|
Packit Service |
a8c26c |
size_t asogetsize(size_t volatile*);
|
|
Packit Service |
a8c26c |
size_t asoincsize(size_t volatile*);
|
|
Packit Service |
a8c26c |
size_t asodecsize(size_t volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
void* asocasptr(void volatile*, void*, void*);
|
|
Packit Service |
a8c26c |
void* asogetptr(void volatile*);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
void ASODISC(Asodisc_t*, Asoerror_f);
|
|
Packit Service |
a8c26c |
Asometh_t* asometh(int, void*);
|
|
Packit Service |
a8c26c |
int asoinit(const char*, Asometh_t*, Asodisc_t*);
|
|
Packit Service |
a8c26c |
int asolock(unsigned int volatile*, unsigned int, int);
|
|
Packit Service |
a8c26c |
int asoloop(uintmax_t);
|
|
Packit Service |
a8c26c |
int asorelax(long);
|
|
Packit Service |
a8c26c |
.Ce
|
|
Packit Service |
a8c26c |
.SH DESCRIPTION
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
\fIASO\fP provides functions to perform atomic scalar operations.
|
|
Packit Service |
a8c26c |
The functions on the type \f5uint32_t\fP will be fully described below.
|
|
Packit Service |
a8c26c |
Other functions work similarly on their respective types.
|
|
Packit Service |
a8c26c |
Some of the functions may be macros that call other functions.
|
|
Packit Service |
a8c26c |
64 bit operations are provided if the compiler supports 64 bit integers and/or pointers.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss "TYPES"
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
\f5uint8_t, uint16_t, uint32_t, uint64_t\fP
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
These are \fIunsigned integer\fP types of different sizes in bits.
|
|
Packit Service |
a8c26c |
For example, \f5uint32_t\fP represents the type of unsigned integer with 32 bits or 4 bytes.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss "OPERATIONS"
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss " uint32_t asoget32(uint32_t* from);"
|
|
Packit Service |
a8c26c |
This function returns the value \f5*from\fP.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss " uint32_t asoinc32(uint32_t* dest);"
|
|
Packit Service |
a8c26c |
.Ss " uint32_t asodec32(uint32_t* dest);"
|
|
Packit Service |
a8c26c |
These functions increment \f5*dest\fP by 1 and decrement \f5*dest\fP by 1 in an atomic step.
|
|
Packit Service |
a8c26c |
The return value is the old value in \f5*dest\fP.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
Consider an example where two concurrent threads/processes call \f5asoinc32()\fP
|
|
Packit Service |
a8c26c |
on the same \f5dest\fP with values, say \fIv1\fP and \fIv2\fP.
|
|
Packit Service |
a8c26c |
The eventual value in \f5dest\fP
|
|
Packit Service |
a8c26c |
will be as if \f5*dest += 2\fP was performed in a single-threaded execution.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
That should be constrasted with a situation where, instead of \f5asoinc32()\fP or \f5asodec32()\fP,
|
|
Packit Service |
a8c26c |
only normal increment (++) or decrement (--) were used.
|
|
Packit Service |
a8c26c |
Then, the end result could be either \f5*dest += 1\fP or \f5*dest += 2\fP,
|
|
Packit Service |
a8c26c |
depending on states of the hardware cache and process scheduling.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss " uint32_t asocas32(uint32_t* dest, uint32_t tstval, uint32_t newval);"
|
|
Packit Service |
a8c26c |
This function provides the atomic \fIcompare-and-swap\fP operation.
|
|
Packit Service |
a8c26c |
If the current content of \f5dest\fP is equal to \f5tstval\fP then it will be set to \f5newval\fP.
|
|
Packit Service |
a8c26c |
If multiple threads/processes are performing the same operations only one will succeed with a
|
|
Packit Service |
a8c26c |
return value of \f5tstval\fP.
|
|
Packit Service |
a8c26c |
The return value is the old value in \f5*dest\fP.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss " void asorelax(long nsec)"
|
|
Packit Service |
a8c26c |
This function causes the calling process or thread to briefly pause
|
|
Packit Service |
a8c26c |
for \f5nsec\fP nanoseconds.
|
|
Packit Service |
a8c26c |
It is useful to implement tight loops that occasionally yield control.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss " int asolock(unsigned int* lock, unsigned int key, int type)"
|
|
Packit Service |
a8c26c |
This function uses \f5key\fP, a non-zero unsigned integer, to lock or unlock the \f5lock\fP.
|
|
Packit Service |
a8c26c |
It returns \f50\fP on success and \f5-1\fP on failure.
|
|
Packit Service |
a8c26c |
The argument \f5type\fP can take one of the following values:
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_UNLOCK\fP:
|
|
Packit Service |
a8c26c |
This unlocks the lock if it was locked with \f5key\fP. It is an error to try
|
|
Packit Service |
a8c26c |
unlocking a lock of a different key.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_TRYLOCK\fP:
|
|
Packit Service |
a8c26c |
This makes a single attempt to use the given \f5key\fP to acquire a lock.
|
|
Packit Service |
a8c26c |
An error will result if the lock is already locked with a different key.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_LOCK\fP:
|
|
Packit Service |
a8c26c |
This is a regular locking call. If the lock is locked with a different key,
|
|
Packit Service |
a8c26c |
this call will wait until the lock is open, then lock it with the given \f5key\fP.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_SPINLOCK\fP:
|
|
Packit Service |
a8c26c |
Regardless of what key is currently locking the lock,
|
|
Packit Service |
a8c26c |
this call will always wait until the lock is open, then lock it with the given \f5key\fP.
|
|
Packit Service |
a8c26c |
Note that, if the lock is already locked with \f5key\fP, this call can result
|
|
Packit Service |
a8c26c |
in a deadlock unless that lock can be opened by some other mechanism, e.g.,
|
|
Packit Service |
a8c26c |
by a different process or thread.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss " int asoloop(uintmax_t iteration);"
|
|
Packit Service |
a8c26c |
This function is used to implement spin locks that periodically relinquish the processor:
|
|
Packit Service |
a8c26c |
.Cs
|
|
Packit Service |
a8c26c |
uintmax_t iteration;
|
|
Packit Service |
a8c26c |
iteration = 0;
|
|
Packit Service |
a8c26c |
for (;;) {
|
|
Packit Service |
a8c26c |
/* test resource with an aso*() call */
|
|
Packit Service |
a8c26c |
if (asoloop(++iteration))
|
|
Packit Service |
a8c26c |
/* an error occurred */;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
.Ce
|
|
Packit Service |
a8c26c |
The value of \f5iteration\fP should be \f51\fP (\fInot\fP \f50\fP) for the first loop iteration.
|
|
Packit Service |
a8c26c |
\f50\fP is returned on success, \f5-1\fP on failure.
|
|
Packit Service |
a8c26c |
If \f5iteration mod 4\fP is \f50\fP then \f5asorelax(1)\fP is called to temporarily relinquish
|
|
Packit Service |
a8c26c |
the processor.
|
|
Packit Service |
a8c26c |
If \f5Asodisc_t.hung != 0\fP and \f5Asodisc_t.errorf != 0\fP and
|
|
Packit Service |
a8c26c |
\f5iteration mod (2**Asodisc_t.hung-1)\fP is \f50\fP,
|
|
Packit Service |
a8c26c |
then \f5Asodisc_t.errorf\fP is called with type \f5ASO_HUNG\fP
|
|
Packit Service |
a8c26c |
and \f5-1\fP is returned.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss "DISCIPLINE"
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
The Asodisc_t discipline structure allows the caller to modify default behavior.
|
|
Packit Service |
a8c26c |
The \fIASO\fP discipline is global for all threads and forked children of the current process.
|
|
Packit Service |
a8c26c |
The discipline is set and modified by the \f5asoinit()\fP function, described below.
|
|
Packit Service |
a8c26c |
The structure members are:
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5uint32_t version;\fP
|
|
Packit Service |
a8c26c |
This must be set to \f5ASO_VERSION\fP by the caller and is used by the implementation to detect
|
|
Packit Service |
a8c26c |
release differences between the caller and the implementation.
|
|
Packit Service |
a8c26c |
The version is integer of the form \fIYYYYMMDD\fP where \fIYYYY\fP is the release year, \fIMM\fP
|
|
Packit Service |
a8c26c |
is the release month, and \fIDD\fP is the release day of month.
|
|
Packit Service |
a8c26c |
This allows the implementation to be forwards and backwards binary compatible with all releases.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5unsigned int hung;\fP
|
|
Packit Service |
a8c26c |
An error occurs if \f5asoloop\fP() is called \f52**Asometh_t.hung\fP times without gaining access to the loop resource.
|
|
Packit Service |
a8c26c |
The default value \f50\fP disables the test.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5Asoerror_f errorf;\fP
|
|
Packit Service |
a8c26c |
\f5int (*errorf)(int type, const char* mesg);\fP
|
|
Packit Service |
a8c26c |
If \f5errorf\fP != \f50\fP then it is called for each \fIASO\fP fatal library condition.
|
|
Packit Service |
a8c26c |
\f5type\fP may be one of: \f5ASO_METHOD\fP - a method error; \f5ASO_HUNG\fP - \f5asoloop\fP() was called
|
|
Packit Service |
a8c26c |
\f52**Asometh_t.hung\fP times with no access to the loop resource.
|
|
Packit Service |
a8c26c |
\f5mesg\fP is a 0-terminated messsage description.
|
|
Packit Service |
a8c26c |
.Ss " void ASODISC(Asodisc_t* disc, Asoerror_f errorf);"
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
This function-like-macro initializes \f5disc->version = ASO_VERSION\fP, \f5disc->errorf = errorf\fP,
|
|
Packit Service |
a8c26c |
and the remaining \f5disc\fP members to \f50\fP.
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.Ss "METHODS"
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
Several atomic locking methods are implemented for atomic operations
|
|
Packit Service |
a8c26c |
not supported by \fIintrinsic\fP functions or assembly instructions.
|
|
Packit Service |
a8c26c |
Methods are controlled by the \f5asometh()\fP and \f5asoinit()\fP
|
|
Packit Service |
a8c26c |
functions, described below.
|
|
Packit Service |
a8c26c |
The \fIASO\fP method is global for all threads and forked children of the current process.
|
|
Packit Service |
a8c26c |
A given method may have multiple types.
|
|
Packit Service |
a8c26c |
The methods types are:
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_INTRINSIC\fP:
|
|
Packit Service |
a8c26c |
Some hardware platforms provide machine instructions to implement these operations directly.
|
|
Packit Service |
a8c26c |
In that case, if a local compiler permits, calls to these \fIintrinsic\fP functions
|
|
Packit Service |
a8c26c |
may be translated directly into their corresponding machine instructions.
|
|
Packit Service |
a8c26c |
When necessary the implementation can use only the intrinsic \fIcompare-and-swap\fP
|
|
Packit Service |
a8c26c |
function on the largest integer type to emulate all other \fIASO\fP operations.
|
|
Packit Service |
a8c26c |
The \f5ASO_INTRINSIC\fP method type is the default when supported by the compiler.
|
|
Packit Service |
a8c26c |
It may be used for single-process single-thread, multi-thread, and
|
|
Packit Service |
a8c26c |
multi-process applications.
|
|
Packit Service |
a8c26c |
When supported by the hardware / compiler, the library provides the "\fBintrinsic\fP" method with type
|
|
Packit Service |
a8c26c |
\f5ASO_INTRINSIC|ASO_PROCESS|ASO_THREAD|ASO_SIGNAL\fP.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_SIGNAL\fP:
|
|
Packit Service |
a8c26c |
This method type is suitable only for single-process single-thread applications.
|
|
Packit Service |
a8c26c |
It can be used to provide locking between asyncronous \fBsignal\fP(2) handlers
|
|
Packit Service |
a8c26c |
and the main program.
|
|
Packit Service |
a8c26c |
The library provides the "\fBsignal\fP" method with type \f5ASO_SIGNAL\fP.
|
|
Packit Service |
a8c26c |
This is the default method type when \f5ASO_INTRINSIC\fP is not supported.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_THREAD\fP:
|
|
Packit Service |
a8c26c |
This method type is suitable for single-process single-thread, and multi-thread applications.
|
|
Packit Service |
a8c26c |
It typically requires thread library support, and since the default \f5aso\fP library
|
|
Packit Service |
a8c26c |
is not linked with a thread library, no \f5ASO_THREAD\fP method is provided by default.
|
|
Packit Service |
a8c26c |
Threaded applications must link with \fB-ltaso\fP (before \fB-laso\fP or \fB-last\fP)
|
|
Packit Service |
a8c26c |
in order to access \f5ASO_THREAD\fP methods.
|
|
Packit Service |
a8c26c |
The \fB-ltaso\fP library provides the "\fBspin\fP" (using \fBpthread_spin_lock\fP(3)) and
|
|
Packit Service |
a8c26c |
"\fBmutex"\fP (using \fBpthread_mutex_lock\fP(3)) methods with type \f5ASO_THREAD|ASO_SIGNAL\fP.
|
|
Packit Service |
a8c26c |
.Tp
|
|
Packit Service |
a8c26c |
\f5ASO_PROCESS\fP:
|
|
Packit Service |
a8c26c |
This method type is suitable for single-process single-thread, and multi-process applications.
|
|
Packit Service |
a8c26c |
Some \f5ASO_PROCESS\fP methods may also be suitable for multi-thread applications (if they have the \f5ASO_THREAD\fP type.)
|
|
Packit Service |
a8c26c |
These methods are typically and noticably \fIslow\fP, up to 2 orders of magnitude slower than
|
|
Packit Service |
a8c26c |
\f5ASO_INTRINSIC\fP for some applications.
|
|
Packit Service |
a8c26c |
They are provided as a last resort when other methods are not available.
|
|
Packit Service |
a8c26c |
The library provides the "\fBsemaphore\fP" method with type \f5ASO_PROCESS|ASO_THREAD|ASO_SIGNAL\fP
|
|
Packit Service |
a8c26c |
and the "\fBfcntl\fP" method with type \f5ASO_PROCESS|ASO_SIGNAL\fP.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
.Ss " Asometh_t* asometh(int type, void* data);"
|
|
Packit Service |
a8c26c |
This function looks up methods by type or name.
|
|
Packit Service |
a8c26c |
If type is \f50\fP and \f5data\fP is \f50\fP then the current method is returned; a valid method
|
|
Packit Service |
a8c26c |
will always be returned for this call.
|
|
Packit Service |
a8c26c |
If type is \f50\fP then \f5data\fP is treated as a \f50\fP-terminated string method name;
|
|
Packit Service |
a8c26c |
\f50\fP is returned if no matching method is found.
|
|
Packit Service |
a8c26c |
The pseudo-type \f5ASO_NEXT\fP generates the list of all methods in successive calls:
|
|
Packit Service |
a8c26c |
.Cs
|
|
Packit Service |
a8c26c |
Asometh_t* meth;
|
|
Packit Service |
a8c26c |
meth = 0;
|
|
Packit Service |
a8c26c |
while (meth = asometh(ASO_NEXT, meth))
|
|
Packit Service |
a8c26c |
/* examine meth->... */
|
|
Packit Service |
a8c26c |
.Ce
|
|
Packit Service |
a8c26c |
Otherwise if \f5type\fP is not \f50\fP and not \f5ASO_NEXT\fP it is treated as a combination of the ordered types
|
|
Packit Service |
a8c26c |
\f5ASO_THREAD\fP, \f5ASO_SIGNAL\fP, \f5ASO_INTRINSIC\fP, \f5ASO_PROCESS\fP:
|
|
Packit Service |
a8c26c |
the first method with \f5(meth->type & type) != 0\fP is returned;
|
|
Packit Service |
a8c26c |
\f50\fP is returned if no matching method is found.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
Method names are treated as a name, optionally followed by a list of
|
|
Packit Service |
a8c26c |
\fB,\fP\fIname\fP=\fIvalue\fP details, and optionally ending with \fB,\fP\fIpathname\fP.
|
|
Packit Service |
a8c26c |
The \fBsemaphore\fP method uses \fBsize\fP=\fInumber\fP to specify
|
|
Packit Service |
a8c26c |
the number of semaphores and hashes \fIpathname\fP to determine the semaphore IPC key.
|
|
Packit Service |
a8c26c |
The \fBfcntl\fP method uses \fBsize\fP=\fInumber\fP to specify
|
|
Packit Service |
a8c26c |
the number of 1 byte file locks and uses \fIpathname\fP as the
|
|
Packit Service |
a8c26c |
file to lock using \f5fcntl(F_SETLCK[W])\fP.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
.Ss " int asoinit(const char* details, Asometh_t* meth, Asodisc_t* disc);"
|
|
Packit Service |
a8c26c |
This function sets the global discipline to \f5disc\fP,
|
|
Packit Service |
a8c26c |
closes the current method (releasing its resources),
|
|
Packit Service |
a8c26c |
temporarily instantiates the default method
|
|
Packit Service |
a8c26c |
(either \f5ASO_INTRINSIC\fP if available or \f5AS_SIGNAL\fP otherwise),
|
|
Packit Service |
a8c26c |
and initializes \f5meth\fP and instantiates it as the new method.
|
|
Packit Service |
a8c26c |
If \f5disc\fP is \f50\fP the the global discpline is not modified.
|
|
Packit Service |
a8c26c |
If \f5meth\fP is \f50\fP then \f51\fP is returned if \f5asoinit()\fP has
|
|
Packit Service |
a8c26c |
already been called to initialize a method, otherwise \f50\fP is returned.
|
|
Packit Service |
a8c26c |
If \f5meth->lockf\fP is \f50\fP and \f5(meth->type & ASO_INTRINSIC) != 0\fP
|
|
Packit Service |
a8c26c |
then \f5-1\fP is returned and the current method is not changed.
|
|
Packit Service |
a8c26c |
If an error occurs instantiating \f5meth\fP then the current method is
|
|
Packit Service |
a8c26c |
set to the default and \f5-1\fP is returned.
|
|
Packit Service |
a8c26c |
Otherwise \f50\fP is returned on success.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
Method resources are released by the next \f5asometh()\fP call,
|
|
Packit Service |
a8c26c |
or by an \fIASO\fP cleanup function called via \f5atexit\fP(2).
|
|
Packit Service |
a8c26c |
System global method resources are released on last use;
|
|
Packit Service |
a8c26c |
this includes removing semaphore keys or
|
|
Packit Service |
a8c26c |
physical files that may be used by some methods.
|
|
Packit Service |
a8c26c |
In some cases \fIASO\fP maintains reference counts within
|
|
Packit Service |
a8c26c |
the resource to determine last use.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
An application requiring a specific method must check the default method before
|
|
Packit Service |
a8c26c |
using any \fIASO\fP operations. For example, a threaded application would
|
|
Packit Service |
a8c26c |
do something like this:
|
|
Packit Service |
a8c26c |
.Cs
|
|
Packit Service |
a8c26c |
void* data = 0 /* \fIor\fP a method name string with optional details */
|
|
Packit Service |
a8c26c |
Asometh_t* meth;
|
|
Packit Service |
a8c26c |
if (data || !(asometh(0, 0)->type & (ASO_INTRINSIC|ASO_THREAD))) {
|
|
Packit Service |
a8c26c |
if (!(meth = asometh(ASO_INTRINSIC|ASO_THREAD, data)))
|
|
Packit Service |
a8c26c |
/* error -- suitable method not found */;
|
|
Packit Service |
a8c26c |
else if (asoinit(meth, 0, 0, ASO_VERSION))
|
|
Packit Service |
a8c26c |
/* error -- method initialization error */;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
/* ready for \fIASO\fP operaions */
|
|
Packit Service |
a8c26c |
.Ce
|
|
Packit Service |
a8c26c |
A multi-process application would check for \f5(ASO_INTRINSIC|ASO_PROCESS)\fP
|
|
Packit Service |
a8c26c |
instead of \f5(ASO_INTRINSIC|ASO_THREAD)\fP.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.SH IMPLEMENTATION NOTES
|
|
Packit Service |
a8c26c |
Unlike other \fIAST\fP library discipline/method functions which can instantiate
|
|
Packit Service |
a8c26c |
multiple discpline/method handles within a single process, the \fIASO\fP
|
|
Packit Service |
a8c26c |
library allows only one discipline and method to be set at a time, with the additional
|
|
Packit Service |
a8c26c |
restriction that it may only be set by the main and only thread of the calling process.
|
|
Packit Service |
a8c26c |
For this reason there is no open/close interface with an instantation handle;
|
|
Packit Service |
a8c26c |
instead the global discipline/method is simply initialized by \f5asoinit()\fP.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
\f5ASO_THREAD\fP and \f5ASO_PROCESS\fP methods rely on the \f5Asometh_t.lockf()\fP
|
|
Packit Service |
a8c26c |
being sufficiently "heavy" to flush the calling thread/process memory cache
|
|
Packit Service |
a8c26c |
so the subsequent \fIASO\fP operation operates on the physical memory location
|
|
Packit Service |
a8c26c |
instead of the cached location. There is currently no other portable mechanism
|
|
Packit Service |
a8c26c |
that guarantees this other than the \f5ASO_INTRINSIC\fP method.
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
.PP
|
|
Packit Service |
a8c26c |
.SH AUTHOR
|
|
Packit Service |
a8c26c |
Kiem-Phong Vo, Adam Edgar, and Glenn Fowler
|