A feature request from Peter Zijlstra outlines very well the need for an llstack API that allows the push operation to return whether the stack was empty or not before the operation. Peter wants to use this information to know if a irq_work should be raised when pushing into the stack. Signed-off-by: Mathieu Desnoyers CC: Huang Ying CC: Andi Kleen CC: "lenb@kernel.org" CC: Peter Zijlstra CC: Andrew Morton --- include/linux/llstack.h | 6 +++--- lib/llstack.c | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) Index: linux-2.6-lttng/lib/llstack.c =================================================================== --- linux-2.6-lttng.orig/lib/llstack.c +++ linux-2.6-lttng/lib/llstack.c @@ -8,6 +8,7 @@ * * Copyright 2010,2011 Intel Corp. * Author: Huang Ying + * Copyright 2011 - Mathieu Desnoyers * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -33,8 +34,11 @@ * llstack_push - push a node into a lock-less stack. * @new: new entry to be added * @head: the head for your lock-less stack + * + * Returns 0 if the stack was empty prior to push operation (check performed + * atomically with push), returns 1 otherwise. */ -void llstack_push(struct llstack_node *new, struct llstack_head *head) +int llstack_push(struct llstack_node *new, struct llstack_head *head) { struct llstack_node *entry, *old_entry; @@ -48,6 +52,8 @@ void llstack_push(struct llstack_node *n new->next = entry; cpu_relax(); } while ((entry = cmpxchg(&head->first, old_entry, new)) != old_entry); + + return !!(unsigned long) entry; } EXPORT_SYMBOL_GPL(llstack_push); @@ -56,8 +62,11 @@ EXPORT_SYMBOL_GPL(llstack_push); * @new_first: first entry in batch to be added * @new_last: last entry in batch to be added * @head: the head for your lock-less list + * + * Returns 0 if the stack was empty prior to push operation (check performed + * atomically with push), returns 1 otherwise. */ -void llstack_push_batch(struct llstack_node *new_first, struct llstack_node *new_last, +int llstack_push_batch(struct llstack_node *new_first, struct llstack_node *new_last, struct llstack_head *head) { struct llstack_node *entry, *old_entry; @@ -72,6 +81,8 @@ void llstack_push_batch(struct llstack_n new_last->next = entry; cpu_relax(); } while ((entry = cmpxchg(&head->first, old_entry, new_first)) != old_entry); + + return !!(unsigned long) entry; } EXPORT_SYMBOL_GPL(llstack_push_batch); Index: linux-2.6-lttng/include/linux/llstack.h =================================================================== --- linux-2.6-lttng.orig/include/linux/llstack.h +++ linux-2.6-lttng/include/linux/llstack.h @@ -118,9 +118,9 @@ static inline int llstack_empty(const st return ACCESS_ONCE(head->first) == NULL; } -void llstack_push(struct llstack_node *new, struct llstack_head *head); -void llstack_push_batch(struct llstack_node *new_first, struct llstack_node *new_last, - struct llstack_head *head); +int llstack_push(struct llstack_node *new, struct llstack_head *head); +int llstack_push_batch(struct llstack_node *new_first, struct llstack_node *new_last, + struct llstack_head *head); struct llstack_node *llstack_pop(struct llstack_head *head); struct llstack_node *llstack_pop_all(struct llstack_head *head); #endif /* LLSTACK_H */ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/