ã¡ã¢ãªã®å²ãåœãŠã«åå¥ã®ãœãªã¥ãŒã·ã§ã³ãå¿
èŠã«ãªãããšããããŸãã ããšãã°ã䞊åã¿ã¹ã¯ã§
ãã¹ããªãŒã
ã«ãã£ãŠé«é
ãžã£ãã¯ã«ãã£ãŠã¡ã¢ãªãå²ãåœãŠããã解æŸãããå Žåã
ãã®çµæãæšæºã®ä¿å®çãªã¢ãã±ãŒã¿ãŒã¯ãpthread_mutex / criticalã»ã¯ã·ã§ã³ãžã®ãã¹ãŠã®èŠæ±ããã¥ãŒã«å
¥ããŸãã ãããŠãç§ãã¡ã®ãã«ãã³ã¢ããã»ããµã¯ãã£ãããšæ²ããããšã«æåã®ã®ã¢ã«ä¹ã£ãŠããŸãã
ãããŠãããã«ã€ããŠã©ãããã°ããã§ããïŒ ã¹ã±ãŒã©ãã«ããã¯ããªãŒãã€ãããã¯ã¡ã¢ãªå²ãåœãŠæ¹åŒã®å®è£
ã®è©³çŽ°ã詳ããèŠãŠã¿ãŸãããã Maged M. Michaelã IBMããŒãã¹J.ã¯ããœã³ç 究æã
ç§ãèŠã€ããæãç°¡åãªã³ãŒãã¯ãScott SchneiderãšChristos Antonopoulosã«ããLGPLã®åå¿ã®äžã§æžããããã®ã§ãã æ€èšããŸãã
é ãããå§ããŸããã
ã ãã-ã©ãããã°äžèŠãªããã¯ãåãé€ãããšãã§ããŸããïŒ
çãã¯è¡šé¢ã«ãããŸã-ããã¯ããªãŒãªã¹ãã«ã¡ã¢ãªãå²ãåœãŠãå¿
èŠããããŸãã è¯ãã¢ã€ãã¢-ãããããã®ãããªãªã¹ãã¯ã©ã®ããã«æ§ç¯ãããŸããïŒ
ååæäœã¯ç§ãã¡ãå©ããããã«æ¥ãã§ããŸãã InterlockedCompareExchangeã§ãããã®ã ããããåŸ
ã£ãŠãã ãã-æåŸ
ã§ããæ倧å€ã¯é·ãã__ int64ã§ãã ãããŠäœããã¹ããïŒ ãããŠãããã«äœããã-ã¿ã°ã§ç¬èªã®ãã€ã³ã¿ãå®çŸ©ããŸãã
ã¢ãã¬ã¹ãµã€ãºã46ãããã«å¶éããããšã§ãå¿
èŠãªã¢ããªã³ã64ãããã§é ãããšãã§ããŸãããããã¯åŸã§å¿
èŠã«ãªããŸãã
#pragma pack(1) typedef struct { volatile unsigned __int64 top:46, ocount:18; } top_aba_t;
ã¡ãªã¿ã«ã8/16ãã€ãã®ã¢ã©ã€ã³ã¡ã³ããèãããšã2ã46床ã§ã¯ãªããããã«æ°åºŠãååŸã§ããŸãã æšæºçãªæ¹æ³-çºè¡ãããã¢ãã¬ã¹ã¯å¥æ°ã§ãã£ãŠã¯ãªãããæµ®åå°æ°ç¹ã«åãããŠèª¿æŽããå¿
èŠããããŸãããããŠãã1ã€-ã³ãŒããéåžžã«é·ããªããŸãã ã€ãŸããæšæºã®ãããã¯ãã¹
desc->Next = queue_head; queue_head = desc;
ãã®ãããªãã¹ã¿ã«å€ãããŸã
descriptor_queue old_queue, new_queue; do { old_queue = queue_head; desc->Next = (descriptor*)old_queue.DescAvail; new_queue.DescAvail = (unsigned __int64)desc; new_queue.tag = old_queue.tag + 1; } while (!compare_and_swap64k(queue_head, old_queue, new_queue));
ããã«ããã³ãŒãã倧å¹
ã«é·ããªããèªã¿ã«ãããªããŸãã ãããã£ãŠãæãããªãã®ã¯ãã¿ãã¬ã®äžã§åé€ãããŸãã
ããã¯ããªãŒFIFOãã¥ãŒ
ããã§ç¬èªã®ãã€ã³ã¿ãã§ããã®ã§ããªã¹ããäœæã§ããŸãã
ãããŠãç§ãã¡ã®å Žå-ããšãã°ããã®ããã«æŽåãå¿ããªãã§ãã ãã
typedef struct { unsigned __int64 _pad0[8]; top_aba_t both; unsigned __int64 _pad1[8]; } lf_fifo_queue_t;
ã¢ãããã¯é¢æ°ã§ã®äœæ¥ã®ã©ãã
ã³ãŒãã移æ€ã§ããããã«ãããã€ãã®æœè±¡åãå®çŸ©ããŸãããïŒããšãã°ãWin32ã®å Žåãããã¯æ¬¡ã®ããã«å®è£
ãããŸãïŒã
Win32ã®Atomã©ãã #define fetch_and_store(address, value) InterlockedExchange((PLONG)(address), (value)) #define atmc_add(address, value) InterlockedExchangeAdd((PLONG)(address), (value)) #define compare_and_swap32(address, old_value, new_value) \ (InterlockedCompareExchange(\ (PLONG)(address), (new_value), (old_value))\ == (old_value)) #define compare_and_swap64(address, old_value, new_value) \ (InterlockedCompareExchange64(\ (PLONGLONG)(address), (__int64)(new_value), (__int64)(old_value)) \ == (__int64)(old_value)) #define compare_and_swap_ptr(address, old_value, new_value) \ (InterlockedCompareExchangePointer((address), \ (new_value), (old_value)) \ == (old_value))
ãã©ã¡ãŒã¿ãŒã__int64ã«ãã£ã¹ãããŠãã€ã³ã¿ãŒã§æž¡ãããšã§æ°ãæ£ããªãããã«ãå¥ã®ã¡ãœãããè¿œå ããŸãã
#define compare_and_swap64k(a,b,c) \ compare_and_swap64((volatile unsigned __int64*)&(a), \ *((unsigned __int64*)&(b)), \ *((unsigned __int64*)&(c)))
ããã§ãåºæ¬æ©èœïŒè¿œå ãšåé€ïŒãå®è£
ããæºåãã§ããŸããã
ãªã¹ããæäœããåºæ¬çãªæ©èœãå®çŸ©ãã
static inline int lf_fifo_enqueue(lf_fifo_queue_t *queue, void *element) { top_aba_t old_top; top_aba_t new_top; for(;;) { old_top.ocount = queue->both.ocount; old_top.top = queue->both.top; ((queue_elem_t *)element)->next = (queue_elem_t *)old_top.top; new_top.top = (unsigned __int64)element; new_top.ocount += 1; if (compare_and_swap64k(queue->both, old_top, new_top)) return 0; } }
äœã«æ³šæããå¿
èŠããããŸã-è¿œå ã®éåžžã®æäœã¯ã«ãŒãã«å
ãŸããŠããããã®æ¹æ³ã¯-å€ãå€ã®äžã«æ°ããå€ãæ£åžžã«æžã蟌ã¿ãŸããããåæã«èª°ããå€ãå€ãå€æŽããŠããŸããã ãŸããå€æŽãããå Žå-ãã®åŸããã¹ãŠãç¹°ãè¿ããŸãã ãããŠå¥ã®ç¬é-ç§ãã¡ã®ã«ãŠã³ãã§ã¯ãæåããè©Šã¿ã®æ°ãæžããŸãã äºçŽ°ãªããšã§ãããåè©Šè¡ã¯äžæã®64ãããæŽæ°ãäžããŸãã
ããã¯ããªãŒã®ããŒã¿æ§é ãæ§ç¯ãããã®ã¯ããã®ãããªåçŽãªã·ã£ãŒãããºã ã§ãã
åæ§ã«ãFIFOãªã¹ãã®å
é ããã®åé€ãå®è£
ãããŠããŸãã
lf_fifo_dequeueãšåæ§ static inline void *lf_fifo_dequeue(lf_fifo_queue_t *queue) { top_aba_t head; top_aba_t next; for(;;) { head.top = queue->both.top; head.ocount = queue->both.ocount; if (head.top == 0) return NULL; next.top = (unsigned __int64)(((struct queue_elem_t *)head.top)->next); next.ocount += 1; if (compare_and_swap64k(queue->both, head, next)) return ((void *)head.top); } }
ããã§ããŸã£ããåãããšãããããŸããåé€ãããã®ãããå Žåã¯ãåé€ããããšãããµã€ã¯ã«ã§ãå€ãå€ããŸã æ£ããããã«-åªããŠããŸãããããã-åè©Šè¡ããŸãã
ãããŠãã¡ããããã®ãããªãªã¹ãé
ç®ãåæåããã®ã¯ç°¡åã§ã-ããã«ãããŸãïŒ
lf_fifo_queue_init static inline void lf_fifo_queue_init(lf_fifo_queue_t *queue) { queue->both.top = 0; queue->both.ocount = 0; }
å®éã«ã¢ãã±ãŒã¿ãŒã®ã¢ã€ãã¢
ã¢ãã±ãŒã¿ãŒã«çŽæ¥é²ã¿ãŸãã ã¢ãã±ãŒã¿ãŒã¯é«éã§ãªããã°ãªããŸãã-ãããã£ãŠãã¡ã¢ãªãŒãã¯ã©ã¹ã«åå²ããŸãã 倧ããïŒã·ã¹ãã ããçŽæ¥ååŸïŒãå°ããããµã€ãºã8ãã€ããã2ãããã€ãã®ç¯å²ã®å€ãã®å€ãã®å°ããªãµãã¯ã©ã¹ã«beatãããŠããŸãã
銬ãšã®ãã®ãããªåãã«ããã2ã€ã®åé¡ã解決ããããšãã§ããŸãã æåã®-å°ããªç Žçã¯è¶
é«éã§ç®ç«ã¡ãããŒãã«ã«åå²ãããŠãããšããäºå®ã«ããã1ã€ã®å€§ããªãªã¹ãã«èŒãããšã¯ãããŸããã ãŸãã倧éã®ã¡ã¢ãªã足å
ã«å¹²æžããããšã¯ãªããæçåã®åé¡ã«ã€ãªãããŸããã ããã«ãåãµãã¯ã©ã¹ã«ã¯åããµã€ãºã®ãã¹ãŠã®ãããã¯ãããããããããã®æäœã¯å€§å¹
ã«ç°¡çŽ åãããŸãã
ãããŠããäžç¬ïŒ éžæããå°çãã¹ã¬ããã«æ·»ä»ããŸãïŒãã ãããªãªãŒã¹ã¯ããã§ã¯ãããŸããïŒã ãããã£ãŠã1ç³ã§2矜ã®é³¥ã殺ããŸã-å²ãåœãŠã®å¶åŸ¡ãç°¡çŽ åãããã¹ã¬ããã«ããŒã«ã«ã«å²ãåœãŠãããã¡ã¢ãªã¢ã€ã©ã³ããåã³æ··ãããŸããã
次ã®ãããªãã®ãåŸãããŸãã
ãããŠãããã¯ããŒã¿ãã¹ãŒããŒãããã¯ã«è¡šç€ºãããæ¹æ³ã§ãïŒ
åçã«ã¯4ã€ã®ã±ãŒã¹ããããŸã
- ã¢ã¯ãã£ããªã¹ãŒããŒãããã¯ã«ã¯ããªã¹ãã«ç·šæããã5ã€ã®èŠçŽ ãå«ãŸãããã®ãã¡ã®4ã€ã䜿çšå¯èœã§ãã
- ãããŠã次ã®èŠçŽ ãäºçŽããŸããïŒã¯ã¬ãžãããåç
§ïŒ
- ãã®çµæããããã¯çªå·5ãçºè¡ããŸãã
- ãããŠãããã¯æ»ãããŸããïŒããããéšåçãªãªã¹ãã«å°éããŸããïŒ
ãããããã³ãããã¯èšè¿°åã«ã€ããŠèª¬æããŸã
女ç¥ãã¯ãã«ç¥ã£ãŠãå§ããŸãããã
ããã€ãã®å®æ°ãå®çŸ©ãã
Balnalism a la GRANULARITYããã³PAGE_SIZE struct Descriptor; typedef struct Descriptor descriptor; struct Procheap; typedef struct Procheap procheap; #define TYPE_SIZE sizeof(void*) #define PTR_SIZE sizeof(void*) #define HEADER_SIZE (TYPE_SIZE + PTR_SIZE) #define LARGE 0 #define SMALL 1 #define PAGESIZE 4096 #define SBSIZE (16 * PAGESIZE) #define DESCSBSIZE (1024 * sizeof(descriptor)) #define ACTIVE 0 #define FULL 1 #define PARTIAL 2 #define EMPTY 3 #define MAXCREDITS 64
ãããŠãåµé åãçºæ®ããŠãå¿
èŠãªããŒã¿åãå®çŸ©ããŸãããã ãããã£ãŠããããã¯ãããããããŸã-ããããç¬èªã®ã¯ã©ã¹ã§ãã¯ããçŸåšã®ã¹ã¬ããã«é¢é£ä»ããããŠããŸãã ã¹ãŒããŒãããã¯ã«ã¯ãã¢ã¯ãã£ããªã¹ããšåé
åžãªã¹ãã®2ã€ã®ãã€ã³ã¿ãŒããããŸãã
ããªãã¯å°ããŸã-ããã¯äœã§ããïŒãªãããããããªã«é£ããã®ã§ããïŒ
ãŸãããããäž»ãªãã®ã§ããèŠçŽ ããšã«ãªã¹ãèŠçŽ ãéžæããããšã¯ãæ¡ç®ãåããªãããšã§ãã ã€ãŸããæ°çŸäžã®èŠçŽ ãæã€å€å
žçãªäžæ¹åã®ãªã¹ããå°çãšã€ã¹ã©ãšã«ã«å€ãããŸãã ãªã¹ãã®åèŠçŽ ã«å¯ŸããŠãããŒã¿èªäœãšãªã¹ãã®æ¬¡ã®èŠçŽ ãžã®2ã€ã®äžå¹žãªãã€ã³ã¿ãæ ŒçŽããããã«ã8/16ãã€ããå²ãåœãŠãå¿
èŠããããŸãã
ããã¯æçã§ããïŒ æããã«ããããïŒ ãããŠãäœããã¹ããïŒ ãã®ãšããã§ããããªã¹ãèšè¿°åã500ïŒããšãã°ïŒèŠçŽ ã®ã°ã«ãŒãïŒã¹ãã©ã€ãïŒã«ã°ã«ãŒãåããŸãã ãããŠãèŠçŽ ã§ã¯ãªãã°ã«ãŒãã®ãªã¹ããååŸããŸãã çµæžçã§å®çšçã§ãã¯ã©ã·ãã¯ããŒãžã§ã³ãšåæ§ã«èŠçŽ ãæäœã§ããŸãã ãã¹ãŠã®è³ªåã¯ãã¡ã¢ãªã®éæšæºã®å²ãåœãŠã®ã¿ã§ãã
ããã«ããããã¯å
ã®ãã¹ãŠã®Nextã¯ãåã«é
åã®æ¬¡ã®èŠçŽ ãæããŠããã ãã§ãããã¹ããªãããéžæãããšããã«æ瀺çã«åæåã§ããŸãã å®éãã¹ããªããã®æåŸã®Nextã¯æ¬¡ã®ã¹ããªããã瀺ããŸããããªã¹ããæäœãããšãã芳ç¹ããã¯äœãå€ãããŸããã
ã¡ã¢ãªãããã¯èšè¿°åããã®ããã«æ§ç¯ãããŠããããšã¯ç°¡åã«æšæž¬ã§ããŸãã
ããã§ããã¢ã¯ãã£ãã¯ããã€ãåäœã§äºåã«å²ãåœãŠãããã¡ã¢ãªã®æçãæã€ã¢ã¯ãã£ãã¹ããªããã§ãããFIFOã®ååã«åŸã£ãŠã¡ã¢ãªãçºè¡ããŸãã ã¹ããªããã«å Žæãããå Žåã¯ãããããåãåºããŸãã ããã§ãªãå Žåã¯ããã§ã«å€å
žçãªéšåãªã¹ããæ¢ããŠããŸãã ããã«ãããã«ããªããã°-çŽ æŽããããæ°ããã¹ãã©ã€ãã匷調ããŸãã
第äºã«ããã®ãããªããã³ãã£ã³ã°ãã¯ã¡ã¢ãªãªãŒããŒã©ã³ãåŒãèµ·ãããŸãã64ãã€ãã®é
åã®åœ¢åŒã§8ãã€ãã®ã¡ã¢ãªã«ã¹ãã©ã€ããå²ãåœãŠãããšãã§ãããã¹ãŠã®ããã€ãã®ããŒã¹ãèŠæ±ãããããã§ãã ããã§ããã¹ã¬ããããšã«ç°ãªãã¢ã¯ãã£ããªã¹ãã©ã€ããååšãããããåé¡ãããã«æªåããŸãã
ãã ããå®éã«ã¡ã¢ãªãç©æ¥µçã«äœ¿çšããŠããå Žåã¯ãé床ã倧å¹
ã«åäžããŸãã
ãã¡ãã¯ããããã®ãã®ã§ã
struct Procheap { volatile active Active;
ãããŠã圌ãå¿
èŠãªãã®ã¯æ¬¡ã®ãšããã§ãã
ãã®ã¢ã¯ãã£ã/ããŒã·ã£ã«ã¯äœã§ããïŒ typedef struct { unsigned __int64 ptr:58, credits:6; } active; typedef struct { unsigned __int64 DescAvail:46, tag:18; } descriptor_queue; typedef struct { unsigned __int64 avail:24,count:24, state:2, tag:14; } anchor; typedef struct { lf_fifo_queue_t Partial;
èšè¿°åèªäœã¯ãã©ã°ã¡ã³ãã®èšè¿°åã§ãã
struct Descriptor { struct queue_elem_t lf_fifo_queue_padding; volatile anchor Anchor;
ã©ããã-è¶
èªç¶çã§ã¯ãªãã ã¡ã¢ãªã¯1ã€ã®ã¹ã¬ããã§å²ãåœãŠãããå¥ã®ã¹ã¬ããã§è§£æŸããããããèšè¿°åã«ããŒããšã¹ãŒããŒãããã¯ã®èª¬æãå¿
èŠã§ãã
ããå§ããŸããã
ãŸããããŒã«ã«å€æ°ïŒããŒãããµã€ãºãªã©ïŒãå®çŸ©ããå¿
èŠããããŸãã ãã®ãããªãã®ïŒ
ã°ããŒãã«å€æ°ãªã sizeclass sizeclasses[2048 / GRANULARITY] = { {LF_FIFO_QUEUE_STATIC_INIT, 8, SBSIZE}, {LF_FIFO_QUEUE_STATIC_INIT, 16, SBSIZE}, ... {LF_FIFO_QUEUE_STATIC_INIT, 2024, SBSIZE}, {LF_FIFO_QUEUE_STATIC_INIT, 2032, SBSIZE}, {LF_FIFO_QUEUE_STATIC_INIT, 2040, SBSIZE}, {LF_FIFO_QUEUE_STATIC_INIT, 2048, SBSIZE}, }; #define LF_FIFO_QUEUE_STATIC_INIT {{0, 0, 0, 0, 0, 0, 0, 0}, {0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}} __declspec(thread) procheap* heaps[2048 / GRANULARITY];
ããã§ã¯ãåã®ã»ã¯ã·ã§ã³ã§æ€èšããããã¹ãŠã衚瀺ãããŸãã
__declspec(thread) procheap* heaps[2048 / GRANULARITY];
ããã¯ã¹ã¬ããããšã®ãããã§ãã ãããŠ-ãã¹ãŠã®ããã»ã¹ããšã®èšè¿°åã®ãªã¹ãã
Malloc-ä»çµã¿
ã¡ã¢ãªå²ãåœãŠã®å®éã®ããã»ã¹ããã詳现ã«æ€èšããŠãã ããã ã€ãŸããããã€ãã®æ©èœãç°¡åã«ç¢ºèªã§ããŸãã
- èŠæ±ããããµã€ãºã«å°ãããµã€ãºã®ãããããªãå Žåã¯ãã·ã¹ãã ã«åãåãããŠãã ãã
- ã¡ã¢ãªãé çªã«éžæããŸã-æåã«ã¢ã¯ãã£ããªã¹ãããã次ã«ãã©ã°ã¡ã³ãã®ãªã¹ããããæåŸã«-ã·ã¹ãã ã«æ°ããããŒã¹ãèŠæ±ããŸãã
- ã·ã¹ãã ã«ã¯åžžã«ã¡ã¢ãªããããããã§ãªãå Žåã¯ã«ãŒãã§åŸ
æ©ããå¿
èŠããããŸã
ããã解決çã§ãã
void* my_malloc(size_t sz) { procheap *heap; void* addr;
ãããã¯ãæãäžããåéšåãåå¥ã«æ€èšããŸãã æåããå§ããŸããã-ã·ã¹ãã ããæ°ããããŒã¹ãè¿œå ããŸãã
MallocFromNewSB static void* MallocFromNewSB(procheap* heap) { descriptor* desc; void* addr; active newactive, oldactive; *((unsigned __int64*)&oldactive) = 0; desc = DescAlloc(); desc->sb = AllocNewSB(heap->sc->sbsize, SBSIZE); desc->heap = heap; desc->Anchor.avail = 1; desc->sz = heap->sc->sz; desc->maxcount = heap->sc->sbsize / desc->sz;
å¥è·¡ã¯ãããŸãã-ã¹ãŒããŒãããã¯ãèšè¿°åãäœæãã空ã®ãªã¹ããåæåããã ãã§ãã ãããŠãã¢ã¯ãã£ããªãããã¯ã®ãªã¹ãã«æ°ãããããã¯ãè¿œå ããŸãã ããã§ãå²ãåœãŠã®ã«ãŒãããªãããšã«æ³šæããŠãã ããã 倱æããå Žåã倱æããŸããã ãªããã é¢æ°ã¯ãã§ã«ã«ãŒãããåŒã³åºãããŠããããªã¹ãã«æ¿å
¥ã§ããªãå Žåã¯ã誰ãããããæ¿å
¥ããããšãæå³ããæåã«ã¡ã¢ãªãå²ãåœãŠãå¿
èŠããããŸãã
次ã«ãã¢ã¯ãã£ããªãããã¯ã®ãªã¹ããããããã¯ãéžæããŸããçµå±ãã¹ãŒããŒãããã¯ãéžæããæ¹æ³ãªã©ã¯ãã§ã«åŠç¿ããŸããã
MallocFromActive static void* MallocFromActive(procheap *heap) { active newactive, oldactive; descriptor* desc; anchor oldanchor, newanchor; void* addr; unsigned __int64 morecredits = 0; unsigned long next = 0;
ã¢ã«ãŽãªãºã èªäœã¯åçŽã§ãé¢åãªåœ¢åŒã®èšè¿°ã®ã¿ãå°ãæ··ä¹±ããŸãã å®éãåããã®ãããã°ãã¹ãŒããŒãããã¯ããæ°ããããŒã¹ãåãåºãããã®äºå®ã«æ³šæããŸãã éäžã§ãæåŸã®ããŒã¹ãååŸãããã©ããã確èªããååŸããå Žåã¯ããã«æ³šæããŸãã
ããã«ã¯åŸ®åŠãªç¹ã1ã€ãããŸããã€ãŸããã¹ãŒããŒãããã¯ããæåŸã®ããŒã¹ãååŸããããšãçªç¶å€æããå Žåã次ã®èŠæ±ã¯æ¢ã«äœ¿çšãããŠãããã®ã®ä»£ããã«æ°ããã¹ãŒããŒãããã¯ã®è¿œå ã«ã€ãªãããŸãã ãããŠããããçºèŠãããšããã«ããããã¯ãå²ãåœãŠãããŠãããšããäºå®ãèšé²ããå ŽæããªããªããŸãã ãããã£ãŠãéžæããéšåãéšåãªã¹ãã«å
¥åããŸãã
UpdateActive static void UpdateActive(procheap* heap, descriptor* desc, unsigned __int64 morecredits) { active oldactive, newactive; anchor oldanchor, newanchor; *((unsigned __int64*)&oldactive) = 0; newactive.ptr = (__int64)desc; newactive.credits = morecredits - 1; if (compare_and_swap64k(heap->Active, oldactive, newactive)) return;
ãã®ãšãã»ã€ã®æåŸã®éšåã«ç§»ãåã«ãèšè¿°åã®æäœãæ€èšããæãæ¥ãŸããã
ã¡ã¢ãªãããã¯èšè¿°å
æå§ãã«ããã³ãã«ã®äœææ¹æ³ãåŠã³ãŸãã ããããã©ãã«ïŒ å®éã誰ããå¿ããå Žå-ç§ãã¡ã¯åã«ã¡ã¢ãªå²ãåœãŠãæžããŸãã æçœã§çŸãã解決çã¯ãäžè¬çãªå²ãåœãŠãšåãã¡ã«ããºã ã䜿çšããããšã§ãããæ²ããããª-ããã¯ããç¥ãããŠãããžã§ãŒã¯pkunzip.zipã«ãªããŸãã ãããã£ãŠãååã¯åãã§ããèšè¿°åã®é
åãå«ã倧ããªãããã¯ãéžæããé
åããªãŒããŒãããŒãããšããã«ãæ°ãããããã¯ãäœæããåã®ãããã¯ãšãªã¹ãã«ããŒãžããŸãã
Descalloc static descriptor* DescAlloc() { descriptor_queue old_queue, new_queue; descriptor* desc; for(;;) { old_queue = queue_head; if (old_queue.DescAvail) { new_queue.DescAvail = (unsigned __int64)((descriptor*)old_queue.DescAvail)->Next; new_queue.tag = old_queue.tag + 1; if (compare_and_swap64k(queue_head, old_queue, new_queue)) { desc = (descriptor*)old_queue.DescAvail; break; } } else { desc = AllocNewSB(DESCSBSIZE, sizeof(descriptor)); organize_desc_list((void *)desc, DESCSBSIZE / sizeof(descriptor), sizeof(descriptor)); new_queue.DescAvail = (unsigned long)desc->Next; new_queue.tag = old_queue.tag + 1; if (compare_and_swap64k(queue_head, old_queue, new_queue)) break; munmap((void*)desc, DESCSBSIZE); } } return desc; }
ããŠãåé¡ã¯ããã»ã©åŒ·åãªãœãŒãµãªãŒã§ã¯ãããŸãã-èšè¿°åãæ»ãããšãåŠã¶å¿
èŠããããŸãã ãã ããåãFIFOã«æ»ããŸãã誀ã£ãŠåãåã£ãå Žåã«ã®ã¿æ»ãå¿
èŠãããããããã®äºå®ã¯ããã«æããã«ãªããŸãã ã ããåé¡ã¯ã¯ããã«ç°¡åã§ã
éäŒ void DescRetire(descriptor* desc) { descriptor_queue old_queue, new_queue; do { old_queue = queue_head; desc->Next = (descriptor*)old_queue.DescAvail; new_queue.DescAvail = (unsigned __int64)desc; new_queue.tag = old_queue.tag + 1; } while (!compare_and_swap64k(queue_head, old_queue, new_queue)); }
ãã«ããŒ
ãŸãããªã¹ããªã©ãåæåããããã®è£å©é¢æ°ãæäŸããŸããé¢æ°ã¯èªæã§ããããããªããšã説æããŠãæå³ããããŸããã
çµç¹ãªã¹ã static void organize_list(void* start, unsigned long count, unsigned long stride) { char* ptr; unsigned long i; ptr = (char*)start; for (i = 1; i < count - 1; i++) { ptr += stride; *((unsigned long*)ptr) = i + 1; } }
organise_desc_list static void organize_desc_list(descriptor* start, unsigned long count, unsigned long stride) { char* ptr; unsigned int i; start->Next = (descriptor*)(start + stride); ptr = (char*)start; for (i = 1; i < count - 1; i++) { ptr += stride; ((descriptor*)ptr)->Next = (descriptor*)((char*)ptr + stride); } ptr += stride; ((descriptor*)ptr)->Next = NULL; }
mask_credits static descriptor* mask_credits(active oldactive) { return (descriptor*)oldactive.ptr; }
ã¹ãŒããŒãããã¯ã¯ã·ã¹ãã ããåã«èŠæ±ãããŸãïŒ
static void* AllocNewSB(size_t size, unsigned long alignement) { return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); }
åæ§ã«ããããã¯ããããŒã«ããå°ãèŠæ±ããããšã§å€§ããªãããã¯ãååŸããŸãã
alloc_large_block static void* alloc_large_block(size_t sz) { void* addr = VirtualAlloc(NULL, sz + HEADER_SIZE, MEM_COMMIT, PAGE_READWRITE);
ããã¯ãç®çã®ãµã€ãºã«é©åããããŒãã®ããŒãã«å
ã®æ€çŽ¢ã§ãïŒãµã€ãºã倧ããããå Žåã¯bkbãŒãïŒïŒ
find_heap static procheap* find_heap(size_t sz) { procheap* heap;
ãªã¹ãã®ã©ãããŒã¯æ¬¡ã®ãšããã§ãã ãããã¯åã«èª¬æã®ç®çã§è¿œå ãããŸã-ã¢ãã ã®åšãã«ãã¹ã¿ã§ååãªã³ãŒããããã1ã€ã®yté¢æ°ã§æ¯èŒãšã¹ã¯ããã®åšãã«12ãµã€ã¯ã«ãè¿œå ããŸã
ListGetPartial static descriptor* ListGetPartial(sizeclass* sc) { return (descriptor*)lf_fifo_dequeue(&sc->Partial); }
ListPutPartial static void ListPutPartial(descriptor* desc) { lf_fifo_enqueue(&desc->heap->sc->Partial, (void*)desc); }
åé€ã¯ç°¡åã«æ§ç¯ãããŸã-ãªã¹ããäžæçãªãªã¹ãã«åæ§ç¯ããããšã«ããïŒ
ListRemoveEmptyDesc static void ListRemoveEmptyDesc(sizeclass* sc) { descriptor *desc; lf_fifo_queue_t temp = LF_FIFO_QUEUE_STATIC_INIT; while (desc = (descriptor *)lf_fifo_dequeue(&sc->Partial)) { lf_fifo_enqueue(&temp, (void *)desc); if (desc->sb == NULL) DescRetire(desc); else break; } while (desc = (descriptor *)lf_fifo_dequeue(&temp)) lf_fifo_enqueue(&sc->Partial, (void *)desc); }
ãããŠãéšåãªã¹ãã®ããã€ãã®ã©ãããŒ
RemoveEmptyDesc static void RemoveEmptyDesc(procheap* heap, descriptor* desc) { if (compare_and_swap_ptr(&heap->Partial, desc, NULL)) DescRetire(desc); else ListRemoveEmptyDesc(heap->sc); }
HeapGetPartial static descriptor* HeapGetPartial(procheap* heap) { descriptor* desc; do { desc = *((descriptor**)&heap->Partial);
HeapPutPartial static void HeapPutPartial(descriptor* desc) { descriptor* prev; do { prev = (descriptor*)desc->heap->Partial;
æåŸã®ãžã£ãŒã¯-å²ãåœãŠ/解æŸããæºåãã§ããŸããïŒ
ãããŠæåŸã«ãã¹ãã©ã€ãã§ã¯ãªãã¡ã¢ãªå²ãåœãŠãå®è£
ããæºåãã§ããŸãããããã«ã¯ãã§ã«ãã¹ãŠã®å¯èœæ§ããããŸãã
ã¢ã«ãŽãªãºã ã¯åçŽã§ã-ãªã¹ããèŠã€ãããã®äžã®å ŽæãäºçŽãïŒåæã«ç©ºã®ãããã¯ã解æŸãïŒãã¯ã©ã€ã¢ã³ãã«è¿ããŸãã
MallocFromPartial static void* MallocFromPartial(procheap* heap) { descriptor* desc; anchor oldanchor, newanchor; unsigned __int64 morecredits; void* addr; retry: desc = HeapGetPartial(heap); if (!desc) return NULL; desc->heap = heap; do {
次ã«ãã¡ã¢ãªããªã¹ãã«æ»ãæ¹æ³ãæ€èšããŸãã äžè¬ã«ãå€å
žçãªã¢ã«ãŽãªãºã ïŒæž¡ããããã€ã³ã¿ãŒãšèšè¿°åã«æ ŒçŽãããã¢ã³ã«ãŒã«ãã£ãŠèšè¿°åã埩å
ããŸã-å¿
èŠãªã¹ãŒããŒãããã¯ã®å Žæã«è¡ããå¿
èŠãªéšåã空ããšããŠããŒã¯ãããã®ããŒã«ããŸã èªãã§ãã人ãããŒã¯ããŸãã ãããŠãã¡ãããããã€ãã®ãã§ãã¯-ã¹ãŒããŒãããã¯å
šäœã解æŸããå¿
èŠããããã©ãããããã§ãªããã°ããŸã 解æŸãããŠããªãæåŸã®ãã§ãã¯ã§ãã
void my_free(void* ptr) { descriptor* desc; void* sb; anchor oldanchor, newanchor; procheap* heap = NULL; if (!ptr) return;
泚æããå¿
èŠããããã®-解æŸãããããŒã¹ã¯éšåãªã¹ãã«åé¡ããããã§ãã¯ãè¿œå ããã®ãè¯ãã§ããã-ã¢ã¯ãã£ããªã¹ãã©ã€ãã®äžçªäžã«éãããšãçž®éããã±ãŒã¹ãã«ãŒãå
ã§éžæããŠè§£æŸãã®å¹çãåäžããŸãã ããããããã¯ãã§ã«å®¿é¡ã§ãã
çµè«
ãã®éåžžã«éå±ã§é·ãäœæ¥ã®äžã§ãããã¯ããªãŒFIFOãªã¹ãã«ã¢ãã±ãŒã¿ãŒãæ§ç¯ããæ¹æ³ãæ€èšãããããäœã§ããããåŠã³ãã¢ãããã¯ãæäœããããã®å€ãã®ããªãã¯ãåŠã³ãŸããããªã¹ããã¹ãã©ã€ãã«ã°ã«ãŒãåããæ©èœããã¡ã¢ãªãããŒãžã£ã®äœæã ãã§ãªã圹ã«ç«ã€ããšãé¡ã£ãŠããŸããè¿œå è³æ
- ã¹ã±ãŒã©ãã«ãªããã¯ããªãŒã®åçã¡ã¢ãªå²ãåœãŠ
- ããŒãã¡ã¢ãªã¢ãã±ãŒã¿ãŒ
- ã¹ã±ãŒã©ãã«ãªå±ææ§ãèæ
®ãããã«ãã¹ã¬ããã¡ã¢ãªå²ãåœãŠ
çµè«ãšããŠãããŸããŸãªã¢ãã±ãŒã¿ãŒã®é床ã«é¢ãã[3]ã®å³ãããã€ã瀺ããŸãïŒåçãã¯ãªãã¯ã§ããŸãïŒãã芧ã®ãšãããã¢ã«ãŽãªãºã ã¯æããã«åçŽã§ãããæé«ã®ãµã³ãã«ã®ã¬ãã«ã§æ©èœããŸãããã®å€ãã¯åŸã§ç»å ŽããŸããæŽæ°ïŒè©³çŽ°ãªèª¬æãããŠãããSkidanovAlexã«æè¬ããŸãïŒ ocountãå¿
èŠãªçç±ã¯èšäºããæããã§ã¯ãããŸãããããã¯ãããããã¿ã°ä»ããã€ã³ã¿ãŒã®å®è£
ã§ããããã§ãªãå Žåããã®ãããªã·ããªãªã¯å¯èœã ãšããããšã§ãïŒABAåé¡ãšåŒã°ãã-ãããã£ãŠãèšäºã®æ§é ã¯top_aba_tãšåŒã°ããŸãïŒïŒãããæäœã¯æ¬¡ã®ããã«ãªããŸãã do { long snapshot = stack->head; long next = snapshot->next; } while (!cas(&stack->head, next, snapshot));
deque , ocount. : , B ( A -> B). snapshot = A, next = B.
A, C, . :
A -> C -> B.
pop , CAS (stack->head == snapshot, A), stack->head B. C .
ocount , A ocount, CAS .
ããããocountã¯ç¢ºãã«å®éã«ã®ã¿ç¯çŽããŸããçè«çã«ã¯ãã¹ãããã·ã§ãããèŠããŠãã次ã®ã¹ã¬ãããŸã§ãocountã以åãšåãå€ããšããŸã§å¥ã®ã¹ã¬ãããA 2 ^ 18ååé€ã§ããABAåé¡ãåã³çºçããŸãããã¡ãããææ°ã®ããŒããŠã§ã¢ã§ã¯ã誰ããã€ã³ã¿ãŒã«48ããããå²ãåœãŠãŸããã代ããã«ã2ã€ã®64ãããå€æ°ãé£ç¶ããŠäœ¿çšããŸãã1ã€ç®ã¯ãã€ã³ã¿ãŒã®äžã2ã€ç®ã¯ocountã®äžã«ããïŒèŠçŽ Aã®æ¿å
¥ã䌎ãçè«äžã®ã·ããªãªã¯ããã«çè«çã«ãªããŸãïŒãäºécasã䜿çšãããŸãã