github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/runtime/lfstack.c (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Lock-free stack. 6 7 #include "runtime.h" 8 #include "arch_GOARCH.h" 9 10 #ifdef _64BIT 11 // Amd64 uses 48-bit virtual addresses, 47-th bit is used as kernel/user flag. 12 // So we use 17msb of pointers as ABA counter. 13 # define PTR_BITS 47 14 #else 15 # define PTR_BITS 32 16 #endif 17 #define PTR_MASK ((1ull<<PTR_BITS)-1) 18 #define CNT_MASK (0ull-1) 19 20 void 21 runtime·lfstackpush(uint64 *head, LFNode *node) 22 { 23 uint64 old, new; 24 25 if((uintptr)node != ((uintptr)node&PTR_MASK)) { 26 runtime·printf("p=%p\n", node); 27 runtime·throw("runtime·lfstackpush: invalid pointer"); 28 } 29 30 node->pushcnt++; 31 new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS); 32 for(;;) { 33 old = runtime·atomicload64(head); 34 node->next = (LFNode*)(uintptr)(old&PTR_MASK); 35 if(runtime·cas64(head, old, new)) 36 break; 37 } 38 } 39 40 LFNode* 41 runtime·lfstackpop(uint64 *head) 42 { 43 LFNode *node, *node2; 44 uint64 old, new; 45 46 for(;;) { 47 old = runtime·atomicload64(head); 48 if(old == 0) 49 return nil; 50 node = (LFNode*)(uintptr)(old&PTR_MASK); 51 node2 = runtime·atomicloadp(&node->next); 52 new = 0; 53 if(node2 != nil) 54 new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<<PTR_BITS); 55 if(runtime·cas64(head, old, new)) 56 return node; 57 } 58 } 59 60 void 61 runtime·lfstackpop2(uint64 *head, LFNode *node) 62 { 63 node = runtime·lfstackpop(head); 64 FLUSH(&node); 65 }