提交 1b2b28c0 编写于 作者: 微希夷 提交者: yitter

!16 兼容Windows平台

* add PHP extension Win DLL
* 兼容Windows平台
上级 ef94d955
// $Id$
// vim:ft=javascript // vim:ft=javascript
// If your extension references something external, use ARG_WITH ARG_ENABLE('snowdrift', 'snowdrift support', 'no');
// ARG_WITH("snowdrift", "for snowdrift support", "no");
// Otherwise, use ARG_ENABLE
ARG_ENABLE("snowdrift", "enable snowdrift support", "no");
if (PHP_SNOWDRIFT != "no") { if (PHP_SNOWDRIFT != "no") {
AC_DEFINE('HAVE_SNOWDRIFT', 1, 'snowdrift support enabled');
snowdrift_source_file="snowdrift.c\ snowdrift_source_file="snowdrift.c\
src/snowflake/snowflake.c\ src/snowflake/snowflake.c\
src/snowflake/shm.c\ src/snowflake/shm.c\
src/snowflake/spinlock.c src/snowflake/spinlock.c"
" EXTENSION("snowdrift", snowdrift_source_file, null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
EXTENSION("snowdrift", $snowdrift_source_file, PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
} }
...@@ -66,9 +66,8 @@ static int snowdrift_init() ...@@ -66,9 +66,8 @@ static int snowdrift_init()
shmctx.size = wid_num * sizeof(snowflake); shmctx.size = wid_num * sizeof(snowflake);
if (shm_alloc(&shmctx) == -1) if (shm_alloc(&shmctx) == -1)
{ {
return FAILURE; return FAILURE;
} }
bzero(shmctx.addr, wid_num * sizeof(snowflake));
sf = (snowflake *)shmctx.addr; sf = (snowflake *)shmctx.addr;
int i; int i;
for (i = 0; i < wid_num; i++) for (i = 0; i < wid_num; i++)
...@@ -92,7 +91,6 @@ static int snowdrift_init() ...@@ -92,7 +91,6 @@ static int snowdrift_init()
{ {
return FAILURE; return FAILURE;
} }
bzero(shmctx.addr, sizeof(snowflake));
sf = (snowflake *)shmctx.addr; sf = (snowflake *)shmctx.addr;
sf->Method = SD_G(Method); sf->Method = SD_G(Method);
sf->BaseTime = SD_G(BaseTime); sf->BaseTime = SD_G(BaseTime);
...@@ -138,7 +136,7 @@ PHP_METHOD(snowdrift, NextNumId) ...@@ -138,7 +136,7 @@ PHP_METHOD(snowdrift, NextNumId)
{ {
zend_long num = 1; zend_long num = 1;
zend_long wid = SD_G(WorkerId); zend_long wid = SD_G(WorkerId);
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &num, &wid) == FAILURE) if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &num, &wid) == FAILURE)
{ {
RETURN_FALSE; RETURN_FALSE;
} }
......
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef WIN32
#include "windows.h"
#else
#include <sys/mman.h> #include <sys/mman.h>
#endif
#include "shm.h" #include "shm.h"
#ifdef MAP_ANON #ifdef WIN32
#define NAME "SnowDrift"
static HANDLE hMapFile;
int shm_alloc(struct shm *shm) int shm_alloc(struct shm* shm) {
{ hMapFile = CreateFileMapping(
shm->addr = (void *)mmap(NULL, shm->size, INVALID_HANDLE_VALUE,
PROT_READ | PROT_WRITE, NULL,
MAP_ANONYMOUS | MAP_SHARED, -1, 0); PAGE_READWRITE,
0,
shm->size,
NAME
);
if (hMapFile == NULL)
{
return 0;
}
LPVOID pBuffer = (LPTSTR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, shm->size);
if (pBuffer == NULL)
{
CloseHandle(hMapFile);
return 0;
}
memset((char*)pBuffer, 0, shm->size);
shm->addr = (void*)pBuffer;
return 1;
}
void shm_free(struct shm* shm) {
UnmapViewOfFile(shm->addr);
CloseHandle(hMapFile);
}
if (shm->addr == NULL) #elif defined(MAP_ANON)
{
return -1;
}
return 0; int shm_alloc(struct shm* shm)
{
shm->addr = (void*)mmap(NULL, shm->size,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (shm->addr == NULL)
{
return -1;
}
bzero(shm->addr, shm->size);
return 0;
} }
void shm_free(struct shm *shm) void shm_free(struct shm* shm)
{ {
if (shm->addr) if (shm->addr)
{ {
munmap((void *)shm->addr, shm->size); munmap((void*)shm->addr, shm->size);
} }
} }
#else #else
int shm_alloc(struct shm *shm) int shm_alloc(struct shm* shm)
{ {
int fd; int fd;
fd = open("/dev/zero", O_RDWR);
if (fd == -1)
{
return -1;
}
shm->addr = (void *)mmap(NULL, shm->size, fd = open("/dev/zero", O_RDWR);
PROT_READ | PROT_WRITE, if (fd == -1)
MAP_SHARED, fd, 0); {
return -1;
}
close(fd); shm->addr = (void*)mmap(NULL, shm->size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (shm->addr == NULL) close(fd);
{
return -1;
}
return 0; if (shm->addr == NULL)
{
return -1;
}
bzero(shm->addr, shm->size);
return 0;
} }
void shm_free(struct shm *shm) void shm_free(struct shm* shm)
{ {
if (shm->addr) if (shm->addr)
{ {
munmap((void *)shm->addr, shm->size); munmap((void*)shm->addr, shm->size);
} }
} }
#endif #endif
#ifdef WIN32
#include "windows.h"
#include <sys/timeb.h>
#else
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "snowflake.h" #include "snowflake.h"
#include "spinlock.h" #include "spinlock.h"
#if defined(WIN32)
#include "windows.h"
#endif
// static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake); // static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake);
static inline uint64_t NextOverCostId(snowflake *flake); static inline uint64_t NextOverCostId(snowflake* flake);
static inline uint64_t NextNormalId(snowflake *flake); static inline uint64_t NextNormalId(snowflake* flake);
static inline uint64_t GetCurrentTimeTick(snowflake *flake); static inline uint64_t GetCurrentTimeTick(snowflake* flake);
static inline uint64_t GetNextTimeTick(snowflake *flake); static inline uint64_t GetNextTimeTick(snowflake* flake);
static inline uint64_t CalcId(snowflake *flake); static inline uint64_t CalcId(snowflake* flake);
static inline uint64_t CalcTurnBackId(snowflake *flake); static inline uint64_t CalcTurnBackId(snowflake* flake);
static inline uint64_t GetCurrentTime(); static inline uint64_t GetSysCurrentTime();
int ncpu; int ncpu;
uint16_t spin = 2048; uint16_t spin = 2048;
uint32_t pid = 0; uint32_t pid = 0;
void Config(snowflake *flake) void Config(snowflake* flake)
{ {
if (pid == 0) if (pid == 0)
{ {
pid = (uint32_t)getpid(); #ifdef WIN32
#if defined(WIN32) pid = (uint32_t)GetCurrentProcessId();
SYSTEM_INFO sysInfo; SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo); GetSystemInfo(&sysInfo);
ncpu = sysInfo.dwNumberOfProcessors; ncpu = sysInfo.dwNumberOfProcessors;
#else #else
ncpu = sysconf(_SC_NPROCESSORS_ONLN); pid = (uint32_t)getpid();
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
#endif #endif
if (ncpu <= 0) if (ncpu <= 0)
{ {
ncpu = 1; ncpu = 1;
} }
} }
if (flake->BaseTime == 0) if (flake->BaseTime == 0)
{ {
flake->BaseTime = 1582136402000; flake->BaseTime = 1582136402000;
} }
else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetCurrentTime()) else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetSysCurrentTime())
{ {
perror("BaseTime error."); perror("BaseTime error.");
exit(1); exit(1);
} }
// 2.WorkerIdBitLength // 2.WorkerIdBitLength
if (flake->WorkerIdBitLength <= 0) if (flake->WorkerIdBitLength <= 0)
{ {
perror("WorkerIdBitLength error.(range:[1, 21])"); perror("WorkerIdBitLength error.(range:[1, 21])");
exit(1); exit(1);
} }
if (flake->SeqBitLength + flake->WorkerIdBitLength > 22) if (flake->SeqBitLength + flake->WorkerIdBitLength > 22)
{ {
perror("error:WorkerIdBitLength + SeqBitLength <= 22"); perror("error:WorkerIdBitLength + SeqBitLength <= 22");
exit(1); exit(1);
} }
else else
{ {
flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength; flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength;
} }
// 3.WorkerId // 3.WorkerId
uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1; uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1;
if (maxWorkerIdNumber == 0) if (maxWorkerIdNumber == 0)
{ {
maxWorkerIdNumber = 63; maxWorkerIdNumber = 63;
} }
if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber) if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber)
{ {
perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}"); perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}");
exit(1); exit(1);
} }
// 4.SeqBitLength // 4.SeqBitLength
if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21) if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21)
{ {
perror("SeqBitLength error. (range:[2, 21])"); perror("SeqBitLength error. (range:[2, 21])");
exit(1); exit(1);
} }
else else
{ {
flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength; flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength;
} }
// 5.MaxSeqNumber // 5.MaxSeqNumber
uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1; uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1;
if (maxSeqNumber == 0) if (maxSeqNumber == 0)
{ {
maxSeqNumber = 63; maxSeqNumber = 63;
} }
if (flake->MaxSeqNumber > maxSeqNumber) if (flake->MaxSeqNumber > maxSeqNumber)
{ {
perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]"); perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]");
exit(1); exit(1);
} }
else else
{ {
flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber; flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber;
} }
// 6.MinSeqNumber // 6.MinSeqNumber
if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber) if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber)
{ {
perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]"); perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]");
exit(1); exit(1);
} }
else else
{ {
flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber; flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber;
} }
// 7.Others // 7.Others
flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount; flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount;
flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength; flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength;
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
flake->Method = flake->Method; flake->Method = flake->Method;
} }
// static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake) // static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake)
...@@ -130,160 +132,169 @@ void Config(snowflake *flake) ...@@ -130,160 +132,169 @@ void Config(snowflake *flake)
// } // }
// } // }
static inline uint64_t NextOverCostId(snowflake *flake) static inline uint64_t NextOverCostId(snowflake* flake)
{ {
uint64_t currentTimeTick = GetCurrentTimeTick(flake); uint64_t currentTimeTick = GetCurrentTimeTick(flake);
if (currentTimeTick > flake->_LastTimeTick) if (currentTimeTick > flake->_LastTimeTick)
{ {
// EndOverCostAction(currentTimeTick, flake); // EndOverCostAction(currentTimeTick, flake);
flake->_LastTimeTick = currentTimeTick; flake->_LastTimeTick = currentTimeTick;
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
flake->_IsOverCost = 0; flake->_IsOverCost = 0;
flake->_OverCostCountInOneTerm = 0; flake->_OverCostCountInOneTerm = 0;
// flake->_GenCountInOneTerm = 0; // flake->_GenCountInOneTerm = 0;
return CalcId(flake); return CalcId(flake);
} }
if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount) if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount)
{ {
// EndOverCostAction(currentTimeTick, flake); // EndOverCostAction(currentTimeTick, flake);
flake->_LastTimeTick = GetNextTimeTick(flake); flake->_LastTimeTick = GetNextTimeTick(flake);
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
flake->_IsOverCost = 0; flake->_IsOverCost = 0;
flake->_OverCostCountInOneTerm = 0; flake->_OverCostCountInOneTerm = 0;
// flake->_GenCountInOneTerm = 0; // flake->_GenCountInOneTerm = 0;
return CalcId(flake); return CalcId(flake);
} }
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
{ {
flake->_LastTimeTick++; flake->_LastTimeTick++;
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
flake->_IsOverCost = 1; flake->_IsOverCost = 1;
flake->_OverCostCountInOneTerm++; flake->_OverCostCountInOneTerm++;
// flake->_GenCountInOneTerm++; // flake->_GenCountInOneTerm++;
return CalcId(flake); return CalcId(flake);
} }
// flake->_GenCountInOneTerm++; // flake->_GenCountInOneTerm++;
return CalcId(flake); return CalcId(flake);
} }
static inline uint64_t NextNormalId(snowflake *flake) static inline uint64_t NextNormalId(snowflake* flake)
{ {
uint64_t currentTimeTick = GetCurrentTimeTick(flake); uint64_t currentTimeTick = GetCurrentTimeTick(flake);
if (currentTimeTick < flake->_LastTimeTick) if (currentTimeTick < flake->_LastTimeTick)
{ {
if (flake->_TurnBackTimeTick < 1) if (flake->_TurnBackTimeTick < 1)
{ {
flake->_TurnBackTimeTick = flake->_LastTimeTick - 1; flake->_TurnBackTimeTick = flake->_LastTimeTick - 1;
flake->_TurnBackIndex++; flake->_TurnBackIndex++;
if (flake->_TurnBackIndex > 4) if (flake->_TurnBackIndex > 4)
{ {
flake->_TurnBackIndex = 1; flake->_TurnBackIndex = 1;
} }
} }
return CalcTurnBackId(flake); return CalcTurnBackId(flake);
} }
if (flake->_TurnBackTimeTick > 0) if (flake->_TurnBackTimeTick > 0)
{ {
flake->_TurnBackTimeTick = 0; flake->_TurnBackTimeTick = 0;
} }
if (currentTimeTick > flake->_LastTimeTick) if (currentTimeTick > flake->_LastTimeTick)
{ {
flake->_LastTimeTick = currentTimeTick; flake->_LastTimeTick = currentTimeTick;
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
return CalcId(flake); return CalcId(flake);
} }
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
{ {
// flake->_TermIndex++; // flake->_TermIndex++;
flake->_LastTimeTick++; flake->_LastTimeTick++;
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
flake->_IsOverCost = 1; flake->_IsOverCost = 1;
flake->_OverCostCountInOneTerm = 1; flake->_OverCostCountInOneTerm = 1;
// flake->_GenCountInOneTerm = 1; // flake->_GenCountInOneTerm = 1;
return CalcId(flake); return CalcId(flake);
} }
return CalcId(flake); return CalcId(flake);
} }
static inline uint64_t GetCurrentTime() static inline uint64_t GetSysCurrentTime()
{ {
struct timeval t; #ifdef WIN32
gettimeofday(&t, NULL); FILETIME file_time;
return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000); GetSystemTimeAsFileTime(&file_time);
uint64_t time = ((uint64_t)file_time.dwLowDateTime) + ((uint64_t)file_time.dwHighDateTime << 32);
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
return (uint64_t)((time - EPOCH) / 10000LL);
#else
struct timeval t;
gettimeofday(&t, NULL);
return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000);
#endif
} }
static inline uint64_t GetCurrentTimeTick(snowflake *flake) static inline uint64_t GetCurrentTimeTick(snowflake* flake)
{ {
return GetCurrentTime() - flake->BaseTime; return GetSysCurrentTime() - flake->BaseTime;
} }
static inline uint64_t GetNextTimeTick(snowflake *flake) static inline uint64_t GetNextTimeTick(snowflake* flake)
{ {
uint64_t tempTimeTicker = GetCurrentTimeTick(flake); uint64_t tempTimeTicker = GetCurrentTimeTick(flake);
while (tempTimeTicker <= flake->_LastTimeTick) while (tempTimeTicker <= flake->_LastTimeTick)
{ {
tempTimeTicker = GetCurrentTimeTick(flake); tempTimeTicker = GetCurrentTimeTick(flake);
} }
return tempTimeTicker; return tempTimeTicker;
} }
static inline uint64_t CalcId(snowflake *flake) static inline uint64_t CalcId(snowflake* flake)
{ {
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber); uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber);
flake->_CurrentSeqNumber++; flake->_CurrentSeqNumber++;
return result; return result;
} }
static inline uint64_t CalcTurnBackId(snowflake *flake) static inline uint64_t CalcTurnBackId(snowflake* flake)
{ {
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick); uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick);
flake->_TurnBackTimeTick--; flake->_TurnBackTimeTick--;
return result; return result;
} }
static inline uint64_t NextSonwId(snowflake *flake) static inline uint64_t NextSonwId(snowflake* flake)
{ {
uint64_t currentTimeTick = GetCurrentTimeTick(flake); uint64_t currentTimeTick = GetCurrentTimeTick(flake);
if (flake->_LastTimeTick == currentTimeTick) if (flake->_LastTimeTick == currentTimeTick)
{ {
flake->_CurrentSeqNumber++; flake->_CurrentSeqNumber++;
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) if (flake->_CurrentSeqNumber > flake->MaxSeqNumber)
{ {
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
currentTimeTick = GetNextTimeTick(flake); currentTimeTick = GetNextTimeTick(flake);
} }
} }
else else
{ {
flake->_CurrentSeqNumber = flake->MinSeqNumber; flake->_CurrentSeqNumber = flake->MinSeqNumber;
} }
flake->_LastTimeTick = currentTimeTick; flake->_LastTimeTick = currentTimeTick;
return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber); return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber);
} }
static inline uint64_t GetId(snowflake *flake) static inline uint64_t GetId(snowflake* flake)
{ {
return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake); return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake);
} }
uint64_t NextId(snowflake *flake) uint64_t NextId(snowflake* flake)
{ {
spin_lock(&flake->_Lock, pid); spin_lock(&flake->_Lock, pid);
uint64_t id = GetId(flake); uint64_t id = GetId(flake);
spin_unlock(&flake->_Lock, pid); spin_unlock(&flake->_Lock, pid);
return id; return id;
} }
uint64_t *NextNumId(snowflake *flake, uint32_t num) uint64_t* NextNumId(snowflake* flake, uint32_t num)
{ {
uint64_t *arr = (uint64_t *)malloc(sizeof(uint64_t) * num); uint64_t* arr = (uint64_t*)malloc(sizeof(uint64_t) * num);
spin_lock(&flake->_Lock, pid); spin_lock(&flake->_Lock, pid);
uint32_t i; uint32_t i;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
arr[i] = GetId(flake); arr[i] = GetId(flake);
} }
spin_unlock(&flake->_Lock, pid); spin_unlock(&flake->_Lock, pid);
return arr; return arr;
} }
#include <stdlib.h> #include <stdlib.h>
#ifdef WIN32
#include "windows.h"
#else
#include <sched.h> #include <sched.h>
#endif
#include "spinlock.h" #include "spinlock.h"
extern int ncpu; extern int ncpu;
extern int spin; extern int spin;
void spin_lock(atomic_t *lock, uint32_t pid) void spin_lock(atomic_t* lock, uint32_t pid)
{ {
int i, n; int i, n;
for (;;) for (;;)
{ {
if (*lock == 0 && if (*lock == 0 &&
__sync_bool_compare_and_swap(lock, 0, pid)) #ifdef WIN32
{ InterlockedCompareExchange(lock, pid, 0) == 0
return; #else
} __sync_bool_compare_and_swap(lock, 0, pid)
#endif
if (ncpu > 1) )
{ {
return;
for (n = 1; n < spin; n <<= 1) }
{
if (ncpu > 1)
for (i = 0; i < n; i++) {
{
__asm("pause"); for (n = 1; n < spin; n <<= 1)
} {
if (*lock == 0 && for (i = 0; i < n; i++)
__sync_bool_compare_and_swap(lock, 0, pid)) {
{ #ifdef WIN32
return; MemoryBarrier();
} #else
} __asm("pause");
} #endif
}
sched_yield();
} if (*lock == 0 &&
#ifdef WIN32
InterlockedCompareExchange(lock, pid, 0) == 0
#else
__sync_bool_compare_and_swap(lock, 0, pid)
#endif
)
{
return;
}
}
}
#ifdef WIN32
SwitchToThread();
#else
sched_yield();
#endif
}
} }
void spin_unlock(atomic_t *lock, uint32_t pid) void spin_unlock(atomic_t* lock, uint32_t pid)
{ {
__sync_bool_compare_and_swap(lock, pid, 0); #ifdef WIN32
InterlockedCompareExchange(lock, 0, pid);
#else
__sync_bool_compare_and_swap(lock, pid, 0);
#endif
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册