X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=rcuja%2Frcuja-internal.h;h=96e9dabf6225d58ebb91e445c574c8a21ecc3551;hb=7d67da99e337f495c1b4c48636d93fa522bd9dfd;hp=67d121bcda21722f35ec6e2cdc50993aefc5e9a9;hpb=a2a7ff599330d13b146409b95cf054a71114c338;p=userspace-rcu.git diff --git a/rcuja/rcuja-internal.h b/rcuja/rcuja-internal.h index 67d121b..96e9dab 100644 --- a/rcuja/rcuja-internal.h +++ b/rcuja/rcuja-internal.h @@ -23,20 +23,50 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _GNU_SOURCE #include #include #include +#include #include +/* + * Number of least significant pointer bits reserved to represent the + * child type. + */ +#define JA_TYPE_BITS 3 +#define JA_TYPE_MAX_NR (1UL << JA_TYPE_BITS) +#define JA_TYPE_MASK (JA_TYPE_MAX_NR - 1) +#define JA_PTR_MASK (~JA_TYPE_MASK) + +#define JA_ENTRY_PER_NODE 256UL +#define JA_LOG2_BITS_PER_BYTE 3U +#define JA_BITS_PER_BYTE (1U << JA_LOG2_BITS_PER_BYTE) + +#define JA_MAX_DEPTH 9 /* Maximum depth, including leafs */ + +/* + * Entry for NULL node is at index 8 of the table. It is never encoded + * in flags. + */ +#define NODE_INDEX_NULL 8 + +/* + * Number of removals needed on a fallback node before we try to shrink + * it. + */ +#define JA_FALLBACK_REMOVAL_COUNT 8 + /* Never declared. Opaque type used to store flagged node pointers. */ struct cds_ja_inode_flag; +struct cds_ja_inode; /* * Shadow node contains mutex and call_rcu head associated with a node. */ struct cds_ja_shadow_node { struct cds_lfht_node ht_node; /* hash table node */ - struct cds_ja_inode *node; /* reverse mapping and hash table key */ + struct cds_ja_inode_flag *node_flag; /* reverse mapping and hash table key */ /* * mutual exclusion on all nodes belonging to the same tree * position (e.g. both nodes before and after recompaction @@ -45,7 +75,9 @@ struct cds_ja_shadow_node { pthread_mutex_t *lock; unsigned int nr_child; /* number of children in node */ struct rcu_head head; /* for deferred node and shadow node reclaim */ - int is_root; /* is it a root node ? */ + int fallback_removal_count; /* removals left keeping fallback */ + int level; /* level in the tree */ + struct cds_ja *ja; /* toplevel judy array */ }; struct cds_ja { @@ -58,19 +90,53 @@ struct cds_ja { * cache footprint, especially for very small nodes. */ struct cds_lfht *ht; + unsigned long nr_fallback; /* Number of fallback nodes used */ }; +static inline +struct cds_ja_inode_flag *ja_node_flag(struct cds_ja_inode *node, + unsigned long type) +{ + assert(type < (1UL << JA_TYPE_BITS)); + return (struct cds_ja_inode_flag *) (((unsigned long) node) | type); +} + +static inline +struct cds_ja_inode *ja_node_ptr(struct cds_ja_inode_flag *node) +{ + return (struct cds_ja_inode *) (((unsigned long) node) & JA_PTR_MASK); +} + +static inline +unsigned long ja_node_type(struct cds_ja_inode_flag *node) +{ + unsigned long type; + + if (ja_node_ptr(node) == NULL) { + return NODE_INDEX_NULL; + } + type = (unsigned int) ((unsigned long) node & JA_TYPE_MASK); + assert(type < (1UL << JA_TYPE_BITS)); + return type; +} + +__attribute__((visibility("protected"))) +void rcuja_free_all_children(struct cds_ja_shadow_node *shadow_node, + struct cds_ja_inode_flag *node_flag, + void (*free_node_cb)(struct rcu_head *head)); + __attribute__((visibility("protected"))) struct cds_ja_shadow_node *rcuja_shadow_lookup_lock(struct cds_lfht *ht, - struct cds_ja_inode *node); + struct cds_ja_inode_flag *node_flag); __attribute__((visibility("protected"))) void rcuja_shadow_unlock(struct cds_ja_shadow_node *shadow_node); __attribute__((visibility("protected"))) -int rcuja_shadow_set(struct cds_lfht *ht, - struct cds_ja_inode *new_node, - struct cds_ja_shadow_node *inherit_from); +struct cds_ja_shadow_node *rcuja_shadow_set(struct cds_lfht *ht, + struct cds_ja_inode_flag *new_node_flag, + struct cds_ja_shadow_node *inherit_from, + struct cds_ja *ja); /* rcuja_shadow_clear flags */ enum { @@ -80,13 +146,14 @@ enum { __attribute__((visibility("protected"))) int rcuja_shadow_clear(struct cds_lfht *ht, - struct cds_ja_inode *node, + struct cds_ja_inode_flag *node_flag, struct cds_ja_shadow_node *shadow_node, unsigned int flags); __attribute__((visibility("protected"))) void rcuja_shadow_prune(struct cds_lfht *ht, - unsigned int flags); + unsigned int flags, + void (*free_node_cb)(struct rcu_head *head)); __attribute__((visibility("protected"))) struct cds_lfht *rcuja_create_ht(const struct rcu_flavor_struct *flavor); @@ -94,16 +161,40 @@ struct cds_lfht *rcuja_create_ht(const struct rcu_flavor_struct *flavor); __attribute__((visibility("protected"))) int rcuja_delete_ht(struct cds_lfht *ht); -#define DEBUG +//#define DEBUG + +#ifdef __linux__ +#include +#endif + +#if defined(_syscall0) +_syscall0(pid_t, gettid) +#elif defined(__NR_gettid) +static inline pid_t gettid(void) +{ + return syscall(__NR_gettid); +} +#else +#warning "use pid as tid" +static inline pid_t gettid(void) +{ + return getpid(); +} +#endif #ifdef DEBUG -#define dbg_printf(fmt, args...) printf("[debug rcuja] " fmt, ## args) +#define dbg_printf(fmt, args...) \ + fprintf(stderr, "[debug rcuja %lu %s()@%s:%u] " fmt, \ + (unsigned long) gettid(), __func__, \ + __FILE__, __LINE__, ## args) #else #define dbg_printf(fmt, args...) \ do { \ /* do nothing but check printf format */ \ if (0) \ - printf("[debug rcuja] " fmt, ## args); \ + fprintf(stderr, "[debug rcuja %lu %s()@%s:%u] " fmt, \ + (unsigned long) gettid(), __func__, \ + __FILE__, __LINE__, ## args); \ } while (0) #endif