/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
#include "asohdr.h"
#else
/*
* ast atomic scalar operations
* AT&T Research
*
* cas { 8 16 32 [64] } subset snarfed from the work by
* Adam Edgar and Kiem-Phong Vo 2010-10-10
*
* lock methods and emulations by
* Glenn Fowler 2011-11-11
*
* hopefully stable by 2012-12-12
*/
#if !_PACKAGE_ast
#if _UWIN
#else
#include <stdio.h>
#endif
#endif
#define ASO_METHOD (&_aso_meth_intrinsic)
#define ASO_LOCKF 0
#else
#define ASO_METHOD (&_aso_meth_signal)
#define ASO_LOCKF _aso_lock_signal
#endif
typedef union
{
uint8_t c[2];
uint16_t i;
} U16_8_t;
typedef union
{
uint8_t c[4];
uint32_t i;
} U32_8_t;
typedef union
{
uint16_t c[2];
uint32_t i;
} U32_16_t;
#ifdef _ast_int8_t
typedef union
{
uint8_t c[8];
uint64_t i;
} U64_8_t;
typedef union
{
uint16_t c[4];
uint64_t i;
} U64_16_t;
typedef union
{
uint32_t c[2];
uint64_t i;
} U64_32_t;
#endif
typedef struct State_s
{
unsigned int hung2;
void* data;
} State_t;
static unsigned int _aso_data_signal;
static ssize_t
{
if (k >= 0)
{
return 0;
}
while (_aso_data_signal++)
return 1;
}
extern Asometh_t _aso_meth_semaphore;
extern Asometh_t _aso_meth_fcntl;
static Asometh_t _aso_meth_intrinsic = { "intrinsic", ASO_INTRINSIC|ASO_PROCESS|ASO_THREAD|ASO_SIGNAL, 0, 0 };
{
#endif
#if _aso_semaphore
#endif
#if _aso_fcntl
#endif
};
{
};
static int
{
char buf[128];
if (b)
else if (a)
else
}
/*
* if type!=0 return lock method for type with name details
* else if name!=0 return lock method matching <name>[,<details>]
* else return the current lock method
* 0 returned on error
*
* the user visible asometh() calls this function
* it allows, e.g., for -ltaso to provide an asometh() intercept
* that prepends its ASO_THREAD methods ahead of the _asometh() methods
*/
{
size_t n;
int i;
char* e;
char* name;
{
return method[0];
return method[i+1];
return 0;
}
if (type)
{
for (i = 0; i < elementsof(method); i++)
{
return method[i];
}
return 0;
}
for (i = 0; i < elementsof(method); i++)
{
if (e)
return method[i];
}
return 0;
}
/*
* clean up lock method on exit
*/
static void
asoexit(void)
{
{
}
}
/*
* initialize lock method
*/
int
{
void* data;
if (disc)
{
}
if (!meth)
{
return -1;
}
{
}
data = 0;
{
asoerror(ASO_EMETHOD, "%s method initialization failed -- reverting to the %s method", meth->name, state.meth->name, 0);
return -1;
}
{
}
return 0;
}
/*
* loop check for hung spin locks
* and periodic relinquishing of the processor
*/
int
{
}
/*
* error checking state.lockf() call
*/
static ssize_t
{
ssize_t r;
return r;
}
/*
* sync and return "current" value
*/
{
int o;
do
{
o = *p;
} while (asocas8(p, o, o) != o);
return o;
}
{
int o;
do
{
o = *p;
} while (asocas16(p, o, o) != o);
return o;
}
{
uint32_t o;
do
{
o = *p;
} while (asocas32(p, o, o) != o);
return o;
}
#ifdef _ast_int8_t
{
uint64_t o;
do
{
o = *p;
} while (asocas64(p, o, o) != o);
return o;
}
#endif
void*
asogetptr(void volatile* p)
{
void* o;
do
{
o = *(void* volatile*)p;
} while (asocasptr(p, o, o) != o);
return o;
}
/*
* increment and return old value
*/
{
ssize_t k;
int o;
#if defined(_aso_inc8)
return _aso_inc8(p);
#else
{
do
{
o = *p;
} while (asocas8(p, o, o + 1) != o);
return o;
}
#endif
o = (*p)++;
return o;
}
{
ssize_t k;
int o;
#if defined(_aso_inc16)
return _aso_inc16(p);
#else
{
do
{
o = *p;
} while (asocas16(p, o, o + 1) != o);
return o;
}
#endif
o = (*p)++;
return o;
}
{
ssize_t k;
int o;
#if defined(_aso_inc32)
return _aso_inc32(p);
#else
{
do
{
o = *p;
} while (asocas32(p, o, o + 1) != o);
return o;
}
#endif
o = (*p)++;
return o;
}
#ifdef _ast_int8_t
{
ssize_t k;
uint64_t o;
#if defined(_aso_inc64)
return _aso_inc64(p);
#else
{
do
{
o = *p;
} while (asocas64(p, o, o + 1) != o);
return o;
}
#endif
o = (*p)++;
return o;
}
#endif
/*
* decrement and return old value
*/
{
ssize_t k;
int o;
#if defined(_aso_dec8)
return _aso_dec8(p);
#else
{
do
{
o = *p;
} while (asocas8(p, o, o - 1) != o);
return o;
}
#endif
o = (*p)--;
return o;
}
{
ssize_t k;
int o;
#if defined(_aso_dec16)
return _aso_dec16(p);
#else
{
do
{
o = *p;
} while (asocas16(p, o, o - 1) != o);
return o;
}
#endif
o = (*p)--;
return o;
}
{
ssize_t k;
int o;
#if defined(_aso_dec32)
return _aso_dec32(p);
#else
{
do
{
o = *p;
} while (asocas32(p, o, o - 1) != o);
return o;
}
#endif
o = (*p)--;
return o;
}
#ifdef _ast_int8_t
{
ssize_t k;
uint64_t o;
#if defined(_aso_dec64)
return _aso_dec64(p);
#else
{
do
{
o = *p;
} while (asocas64(p, o, o - 1) != o);
return o;
}
#endif
o = (*p)--;
return o;
}
#endif
/*
* { 8 16 32 [64] } compare with old, swap with new if same, and return old value
*/
{
ssize_t k;
#if defined(_aso_cas8)
return _aso_cas8(p, o, n);
#elif defined(_aso_cas16)
{
U16_8_t u;
U16_8_t v;
U16_8_t* a;
int s;
int i;
s = (int)(integralof(p) & (sizeof(u.i) - 1));
for (;;)
{
u.i = a->i;
u.c[s] = o;
v.i = u.i;
v.c[s] = n;
if (_aso_cas16(&a->i, u.i, v.i) == u.i)
break;
for (i = 0;; i++)
if (i >= elementsof(u.c))
return a->c[s];
else if (i != s && u.c[i] != a->c[i])
break;
}
return o;
}
#elif defined(_aso_cas32)
{
U32_8_t u;
U32_8_t v;
U32_8_t* a;
int s;
int i;
s = (int)(integralof(p) & (sizeof(u.i) - 1));
for (;;)
{
u.i = a->i;
u.c[s] = o;
v.i = u.i;
v.c[s] = n;
if (_aso_cas32(&a->i, u.i, v.i) == u.i)
break;
for (i = 0;; i++)
if (i >= elementsof(u.c))
return a->c[s];
else if (i != s && u.c[i] != a->c[i])
break;
}
return o;
}
#elif defined(_aso_cas64)
{
U64_8_t u;
U64_8_t v;
U64_8_t* a;
int s;
int i;
s = (int)(integralof(p) & (sizeof(u.i) - 1));
for (;;)
{
u.i = a->i;
u.c[s] = o;
v.i = u.i;
v.c[s] = n;
if (_aso_cas64(&a->i, u.i, v.i) == u.i)
break;
for (i = 0;; i++)
if (i >= elementsof(u.c))
return a->c[s];
else if (i != s && u.c[i] != a->c[i])
break;
}
return o;
}
#endif
if (*p == o)
*p = n;
else
o = *p;
return o;
}
{
ssize_t k;
#if defined(_aso_cas16)
return _aso_cas16(p, o, n);
#elif defined(_aso_cas32)
{
U32_16_t u;
U32_16_t v;
U32_16_t* a;
int s;
int i;
for (;;)
{
u.i = a->i;
u.c[s] = o;
v.i = u.i;
v.c[s] = n;
if (_aso_cas32(&a->i, u.i, v.i) == u.i)
break;
for (i = 0;; i++)
if (i >= elementsof(u.c))
return a->c[s];
else if (i != s && u.c[i] != a->c[i])
break;
}
return o;
}
#elif defined(_aso_cas64)
{
U64_16_t u;
U64_16_t v;
U64_16_t* a;
int s;
int i;
for (;;)
{
u.i = a->i;
u.c[s] = o;
v.i = u.i;
v.c[s] = n;
if (_aso_cas64(&a->i, u.i, v.i) == u.i)
break;
for (i = 0;; i++)
if (i >= elementsof(u.c))
return a->c[s];
else if (i != s && u.c[i] != a->c[i])
break;
}
return o;
}
#endif
if (*p == o)
*p = n;
else
o = *p;
return o;
}
{
ssize_t k;
#if defined(_aso_cas32)
return _aso_cas32(p, o, n);
#elif defined(_aso_cas64)
{
U64_32_t u;
U64_32_t v;
U64_32_t* a;
int s;
int i;
for (;;)
{
u.i = a->i;
u.c[s] = o;
v.i = u.i;
v.c[s] = n;
if (_aso_cas64(&a->i, u.i, v.i) == u.i)
break;
for (i = 0;; i++)
if (i >= elementsof(u.c))
return a->c[s];
else if (i != s && u.c[i] != a->c[i])
break;
}
return o;
}
#endif
if (*p == o)
*p = n;
else
o = *p;
return o;
}
#ifdef _ast_int8_t
{
ssize_t k;
#if defined(_aso_cas64)
return _aso_cas64(p, o, n);
#endif
if (*p == o)
*p = n;
else
o = *p;
return o;
}
#endif
/*
* compare with old, swap with new if same, and return old value
*/
void*
asocasptr(void volatile* p, void* o, void* n)
{
ssize_t k;
#if defined(_aso_casptr)
return _aso_casptr((void**)p, o, n);
#endif
if (*(void* volatile*)p == o)
*(void* volatile*)p = n;
else
o = *(void* volatile*)p;
return o;
}
#endif