mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 08:57:26 +02:00
112 lines
2.1 KiB
C++
112 lines
2.1 KiB
C++
/*
|
|
* Copyright (c)2013-2020 ZeroTier, Inc.
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file in the project's root directory.
|
|
*
|
|
* Change Date: 2024-01-01
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2.0 of the Apache License.
|
|
*/
|
|
/****/
|
|
|
|
#include "Buf.hpp"
|
|
|
|
namespace ZeroTier {
|
|
|
|
#ifdef __GNUC__
|
|
uintptr_t _Buf_pool = 0;
|
|
#else
|
|
std::atomic<uintptr_t> _Buf_pool(0);
|
|
#endif
|
|
|
|
void _Buf_release(void *ptr,std::size_t sz)
|
|
{
|
|
if (ptr) {
|
|
uintptr_t bb;
|
|
const uintptr_t locked = ~((uintptr_t)0);
|
|
for (;;) {
|
|
#ifdef __GNUC__
|
|
bb = __sync_fetch_and_or(&_Buf_pool,locked); // get value of s_pool and "lock" by filling with all 1's
|
|
#else
|
|
bb = s_pool.fetch_or(locked);
|
|
#endif
|
|
if (bb != locked)
|
|
break;
|
|
}
|
|
|
|
((Buf *)ptr)->__nextInPool = bb;
|
|
#ifdef __GNUC__
|
|
__sync_fetch_and_and(&_Buf_pool,(uintptr_t)ptr);
|
|
#else
|
|
s_pool.store((uintptr_t)ptr);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void *_Buf_get()
|
|
{
|
|
uintptr_t bb;
|
|
const uintptr_t locked = ~((uintptr_t)0);
|
|
for (;;) {
|
|
#ifdef __GNUC__
|
|
bb = __sync_fetch_and_or(&_Buf_pool,locked); // get value of s_pool and "lock" by filling with all 1's
|
|
#else
|
|
bb = s_pool.fetch_or(locked);
|
|
#endif
|
|
if (bb != locked)
|
|
break;
|
|
}
|
|
|
|
Buf *b;
|
|
if (bb == 0) {
|
|
#ifdef __GNUC__
|
|
__sync_fetch_and_and(&_Buf_pool,bb);
|
|
#else
|
|
s_pool.store(bb);
|
|
#endif
|
|
b = (Buf *)malloc(sizeof(Buf<>));
|
|
if (!b)
|
|
throw std::bad_alloc();
|
|
} else {
|
|
b = (Buf *)bb;
|
|
#ifdef __GNUC__
|
|
__sync_fetch_and_and(&_Buf_pool,b->__nextInPool);
|
|
#else
|
|
s_pool.store(b->__nextInPool);
|
|
#endif
|
|
}
|
|
|
|
b->__refCount.zero();
|
|
return (void *)b;
|
|
}
|
|
|
|
void freeBufPool()
|
|
{
|
|
uintptr_t bb;
|
|
const uintptr_t locked = ~((uintptr_t)0);
|
|
for (;;) {
|
|
#ifdef __GNUC__
|
|
bb = __sync_fetch_and_or(&_Buf_pool,locked); // get value of s_pool and "lock" by filling with all 1's
|
|
#else
|
|
bb = s_pool.fetch_or(locked);
|
|
#endif
|
|
if (bb != locked)
|
|
break;
|
|
}
|
|
|
|
#ifdef __GNUC__
|
|
__sync_fetch_and_and(&_Buf_pool,(uintptr_t)0);
|
|
#else
|
|
s_pool.store((uintptr_t)0);
|
|
#endif
|
|
|
|
while (bb != 0) {
|
|
uintptr_t next = ((Buf *)bb)->__nextInPool;
|
|
free((void *)bb);
|
|
bb = next;
|
|
}
|
|
}
|
|
|
|
} // namespace ZeroTier
|