From 0599d7de5844a2f838cdf631b9c88b05010ebe5d Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 9 Dec 2015 06:48:15 +0000 Subject: use atomic operations * regcomp.c (onig_chain_link_add): use atomic operation instead of mutex. * regint.h (ONIG_STATE_{INC,DEC}_THREAD): ditto. * regparse.c (PopFreeNode, node_recycle): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52995 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- regparse.c | 93 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) (limited to 'regparse.c') diff --git a/regparse.c b/regparse.c index 094332f90e..0baf02c145 100644 --- a/regparse.c +++ b/regparse.c @@ -1031,7 +1031,43 @@ typedef struct _FreeNode { } FreeNode; static FreeNode* FreeNodeList = (FreeNode* )NULL; + +#define PopFreeNode(n, popped) \ + do { \ + FreeNode* n = FreeNodeList; \ + while (IS_NOT_NULL(n)) { \ + FreeNode* next = n->next; \ + FreeNode *head = ATOMIC_PTR_CAS(FreeNodeList, n, next); \ + if (head == n) { \ + popped; \ + n = next; \ + } \ + else { \ + n = head; /* modified, retry */ \ + } \ + } \ + } while (0) + +#endif + +static void +node_recycle(Node* node) +{ +#ifdef USE_PARSE_TREE_NODE_RECYCLE + FreeNode* n = (FreeNode* )node; + FreeNode* list = FreeNodeList; + FreeNode* l; + + /* THREAD_ATOMIC_START; */ + do { + n->next = l = list; + list = ATOMIC_PTR_CAS(FreeNodeList, list, n); + } while (list != l); + /* THREAD_ATOMIC_END; */ +#else + xfree(node); #endif +} extern void onig_node_free(Node* node) @@ -1053,18 +1089,7 @@ onig_node_free(Node* node) { Node* next_node = NCDR(node); -#ifdef USE_PARSE_TREE_NODE_RECYCLE - { - FreeNode* n = (FreeNode* )node; - - THREAD_ATOMIC_START; - n->next = FreeNodeList; - FreeNodeList = n; - THREAD_ATOMIC_END; - } -#else - xfree(node); -#endif + node_recycle(node); node = next_node; goto start; } @@ -1101,32 +1126,15 @@ onig_node_free(Node* node) break; } -#ifdef USE_PARSE_TREE_NODE_RECYCLE - { - FreeNode* n = (FreeNode* )node; - - THREAD_ATOMIC_START; - n->next = FreeNodeList; - FreeNodeList = n; - THREAD_ATOMIC_END; - } -#else - xfree(node); -#endif + node_recycle(node); } #ifdef USE_PARSE_TREE_NODE_RECYCLE extern int onig_free_node_list(void) { - FreeNode* n; - /* THREAD_ATOMIC_START; */ - while (IS_NOT_NULL(FreeNodeList)) { - n = FreeNodeList; - FreeNodeList = FreeNodeList->next; - xfree(n); - } + PopFreeNode(n, xfree(n)); /* THREAD_ATOMIC_END; */ return 0; } @@ -1138,14 +1146,9 @@ node_new(void) Node* node; #ifdef USE_PARSE_TREE_NODE_RECYCLE - THREAD_ATOMIC_START; - if (IS_NOT_NULL(FreeNodeList)) { - node = (Node* )FreeNodeList; - FreeNodeList = FreeNodeList->next; - THREAD_ATOMIC_END; - return node; - } - THREAD_ATOMIC_END; + /* THREAD_ATOMIC_START; */ + PopFreeNode(n, return (Node* )n); + /* THREAD_ATOMIC_END; */ #endif node = (Node* )xmalloc(sizeof(Node)); @@ -1155,17 +1158,14 @@ node_new(void) #if defined(USE_MULTI_THREAD_SYSTEM) && \ defined(USE_SHARED_CCLASS_TABLE) && \ - defined(USE_PARSE_TREE_NODE_RECYCLE) + defined(USE_PARSE_TREE_NODE_RECYCLE) && \ + 0 static Node* node_new_locked(void) { Node* node; - if (IS_NOT_NULL(FreeNodeList)) { - node = (Node* )FreeNodeList; - FreeNodeList = FreeNodeList->next; - return node; - } + PopFreeNode(n, return (Node* )n); node = (Node* )xmalloc(sizeof(Node)); /* xmemset(node, 0, sizeof(Node)); */ @@ -1195,7 +1195,8 @@ node_new_cclass(void) #if defined(USE_MULTI_THREAD_SYSTEM) && \ defined(USE_SHARED_CCLASS_TABLE) && \ - defined(USE_PARSE_TREE_NODE_RECYCLE) + defined(USE_PARSE_TREE_NODE_RECYCLE) && \ + 0 static Node* node_new_cclass_locked(void) { -- cgit v1.2.3