Re: [lttng-dev] [rp] [RFC] Readiness for URCU release with RCU lock-free hash table

2012-05-03 Thread Mathieu Desnoyers
* Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
 On Wed, May 02, 2012 at 12:16:39AM -0400, Mathieu Desnoyers wrote:
  * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
   On Tue, May 01, 2012 at 05:02:06PM -0400, Mathieu Desnoyers wrote:
* Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
 On Tue, May 01, 2012 at 01:41:36PM -0400, Mathieu Desnoyers wrote:
  * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
   On Tue, May 01, 2012 at 11:21:44AM -0400, Mathieu Desnoyers wrote:
* Mathieu Desnoyers (mathieu.desnoy...@efficios.com) wrote:
 * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
  On Tue, May 01, 2012 at 10:16:09AM -0400, Mathieu Desnoyers 
  wrote:
   Hi!
   
   After 1 year of development, with the last 6-7 months 
   spent polishing
   the API and testing the implementation, I think it is 
   getting about time
   to release the RCU lock-free hash table in a new 
   Userspace RCU version
   (0.7).
   
   I recently described the guarantees provided by the hash 
   table in more
   detail, and created tests for the uniqueness guarantee 
   for traversals
   performed concurrently with add_unique and add_replace 
   operations. I
   also added test modes that create long hash chains, to 
   test corner-cases
   of the hash table.
   
   One small thing I wonder is whether we should document 
   that the hash
   table update operations imply full memory barriers ?
  
  The Linux kernel's rule seems good here -- if a hash-table 
  operation is
  atomic and returns a value, it should imply a full barrier. 
   So:
  
  cds_lfht_new(): No point in claiming barriers -- publishing 
  the
  pointer to the hash table is where the barriers are 
  important.
  
  cds_lfht_destroy(): Ditto.
  
  cds_lfht_lookup(): Not an update (let alone an atomic 
  update), no barriers.
  
  cds_lfht_next_duplicate(): Ditto.
  
  cds_lfht_first(): Ditto.
  
  cds_lfht_next(): Ditto.
  
  cds_lfht_add(): Atomic update, but no return value, so no 
  barrier
  implied.
 
 Yep, makes sense. We use cmpxchg internally to perform the 
 update, but
 it could make sense to eventually use a cmpxchg that has no 
 memory
 barriers to perform this update. So I agree on not providing 
 a memory
 barrier guarantee on the add operation, since it does not 
 return any
 value.
 
  
  cds_lfht_add_unique(): Atomic update that returns a value, 
  so should
  imply a full memory barrier.
 
 add_unique is a bit special:
 
 - if it returns the node received as parameter, it means the 
 add
   succeeded, which imply an update, and thus a memory barrier.

Hrm, thinking further: if we make the add operation not act 
as a
full memory barrier, then the add_unique success should not act 
as a
full mb neither.
   
   Think of it as being similar to the Linux kernel's atomic_inc() 
   and
   atomic_add_return() primitives.  The latter guarantees memory 
   barriers
   and the former does not.
  
  I think add/add_unique vs atomic_inc/atomic_add_return are 
  fundamentally
  different.
  
  atomic_inc:
   - input: increment
   - output: none
   - effect: increment target address value
  
  atomic_add_return:
   - input: increment
   - output: incremented value
   - effect: increment target address value, atomically reading the
 resulting value.
  
  hash table add:
   - input: new node to add
   - output: none
   - effect: atomically add the new node into the table
  
  hash table add_unique (success):
   - input: new node to add
   - output: (we just return whether the operation has succeeded)
   - effect: atomically add the new node into the table
  
  hash table add_unique (failure):
   - input: new node to try adding
   - output: (we just return whether the operation has succeeded)
   - effect: simple lookup (read)
  
  So as we see, the add_unique failure only performs a read. Adding a
  memory barrier before this read would require us to add a memory 
  barrier
  also on the success path, which would degrade performance. The 
  success
  path does: lookup failure, cmpxchg to add the node, retry if 
  changed.
  Adding a memory barrier before the lookup would add an extra memory
  barrier in 

Re: [lttng-dev] [rp] [RFC] Readiness for URCU release with RCU lock-free hash table

2012-05-03 Thread Paul E. McKenney
On Thu, May 03, 2012 at 01:13:30PM -0400, Mathieu Desnoyers wrote:
 * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
  On Wed, May 02, 2012 at 12:16:39AM -0400, Mathieu Desnoyers wrote:
   * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
On Tue, May 01, 2012 at 05:02:06PM -0400, Mathieu Desnoyers wrote:
 * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
  On Tue, May 01, 2012 at 01:41:36PM -0400, Mathieu Desnoyers wrote:
   * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
On Tue, May 01, 2012 at 11:21:44AM -0400, Mathieu Desnoyers 
wrote:
 * Mathieu Desnoyers (mathieu.desnoy...@efficios.com) wrote:
  * Paul E. McKenney (paul...@linux.vnet.ibm.com) wrote:
   On Tue, May 01, 2012 at 10:16:09AM -0400, Mathieu 
   Desnoyers wrote:
Hi!

After 1 year of development, with the last 6-7 months 
spent polishing
the API and testing the implementation, I think it is 
getting about time
to release the RCU lock-free hash table in a new 
Userspace RCU version
(0.7).

I recently described the guarantees provided by the 
hash table in more
detail, and created tests for the uniqueness guarantee 
for traversals
performed concurrently with add_unique and add_replace 
operations. I
also added test modes that create long hash chains, to 
test corner-cases
of the hash table.

One small thing I wonder is whether we should document 
that the hash
table update operations imply full memory barriers ?
   
   The Linux kernel's rule seems good here -- if a 
   hash-table operation is
   atomic and returns a value, it should imply a full 
   barrier.  So:
   
   cds_lfht_new(): No point in claiming barriers -- 
   publishing the
 pointer to the hash table is where the barriers are 
   important.
   
   cds_lfht_destroy(): Ditto.
   
   cds_lfht_lookup(): Not an update (let alone an atomic 
   update), no barriers.
   
   cds_lfht_next_duplicate(): Ditto.
   
   cds_lfht_first(): Ditto.
   
   cds_lfht_next(): Ditto.
   
   cds_lfht_add(): Atomic update, but no return value, so no 
   barrier
 implied.
  
  Yep, makes sense. We use cmpxchg internally to perform the 
  update, but
  it could make sense to eventually use a cmpxchg that has no 
  memory
  barriers to perform this update. So I agree on not 
  providing a memory
  barrier guarantee on the add operation, since it does not 
  return any
  value.
  
   
   cds_lfht_add_unique(): Atomic update that returns a 
   value, so should
 imply a full memory barrier.
  
  add_unique is a bit special:
  
  - if it returns the node received as parameter, it means 
  the add
succeeded, which imply an update, and thus a memory 
  barrier.
 
 Hrm, thinking further: if we make the add operation not act 
 as a
 full memory barrier, then the add_unique success should not 
 act as a
 full mb neither.

Think of it as being similar to the Linux kernel's atomic_inc() 
and
atomic_add_return() primitives.  The latter guarantees memory 
barriers
and the former does not.
   
   I think add/add_unique vs atomic_inc/atomic_add_return are 
   fundamentally
   different.
   
   atomic_inc:
- input: increment
- output: none
- effect: increment target address value
   
   atomic_add_return:
- input: increment
- output: incremented value
- effect: increment target address value, atomically reading the
  resulting value.
   
   hash table add:
- input: new node to add
- output: none
- effect: atomically add the new node into the table
   
   hash table add_unique (success):
- input: new node to add
- output: (we just return whether the operation has succeeded)
- effect: atomically add the new node into the table
   
   hash table add_unique (failure):
- input: new node to try adding
- output: (we just return whether the operation has succeeded)
- effect: simple lookup (read)
   
   So as we see, the add_unique failure only performs a read. Adding 
   a
   memory barrier before this read would require us to add a memory 
   barrier
   also on the success path, which would 

[lttng-dev] [lttng-ust PATCH 2/2] Add 2x int and 2x long types to the Java interface

2012-05-03 Thread Alexandre Montplaisir
Since we have to statically define all the available event types,
offer types for two integers and two longs, which are relatively
common use cases.

Signed-off-by: Alexandre Montplaisir alexandre.montplai...@polymtl.ca
---
 liblttng-ust-java/LTTngUst.c   |   28 
 liblttng-ust-java/LTTngUst.java|   28 
 liblttng-ust-java/lttng_ust_java.h |   18 ++
 3 files changed, 74 insertions(+)

diff --git a/liblttng-ust-java/LTTngUst.c b/liblttng-ust-java/LTTngUst.c
index 0bef89d..9ae3983 100644
--- a/liblttng-ust-java/LTTngUst.c
+++ b/liblttng-ust-java/LTTngUst.c
@@ -35,6 +35,20 @@ JNIEXPORT void JNICALL 
Java_org_lttng_ust_LTTngUst_tracepointInt(JNIEnv *env,
(*env)-ReleaseStringUTFChars(env, ev_name, ev_name_cstr);
 }
 
+JNIEXPORT void JNICALL Java_org_lttng_ust_LTTngUst_tracepointIntInt(JNIEnv 
*env,
+   jobject jobj,
+   jstring ev_name,
+   jint payload1,
+   jint payload2)
+{
+   jboolean iscopy;
+   const char *ev_name_cstr = (*env)-GetStringUTFChars(env, ev_name, 
iscopy);
+
+   tracepoint(lttng_ust_java, int_int_event, ev_name_cstr, payload1, 
payload2);
+
+   (*env)-ReleaseStringUTFChars(env, ev_name, ev_name_cstr);
+}
+
 JNIEXPORT void JNICALL Java_org_lttng_ust_LTTngUst_tracepointLong(JNIEnv *env,
jobject jobj,
jstring ev_name,
@@ -48,6 +62,20 @@ JNIEXPORT void JNICALL 
Java_org_lttng_ust_LTTngUst_tracepointLong(JNIEnv *env,
(*env)-ReleaseStringUTFChars(env, ev_name, ev_name_cstr);
 }
 
+JNIEXPORT void JNICALL Java_org_lttng_ust_LTTngUst_tracepointLongLong(JNIEnv 
*env,
+   jobject jobj,
+   jstring ev_name,
+   jlong payload1,
+   jlong payload2)
+{
+   jboolean iscopy;
+   const char *ev_name_cstr = (*env)-GetStringUTFChars(env, ev_name, 
iscopy);
+
+   tracepoint(lttng_ust_java, long_long_event, ev_name_cstr, payload1, 
payload2);
+
+   (*env)-ReleaseStringUTFChars(env, ev_name, ev_name_cstr);
+}
+
 JNIEXPORT void JNICALL Java_org_lttng_ust_LTTngUst_tracepointString(JNIEnv 
*env,
jobject jobj,
jstring ev_name,
diff --git a/liblttng-ust-java/LTTngUst.java b/liblttng-ust-java/LTTngUst.java
index f4bea32..79ad97a 100644
--- a/liblttng-ust-java/LTTngUst.java
+++ b/liblttng-ust-java/LTTngUst.java
@@ -57,6 +57,20 @@ public abstract class LTTngUst {
 public static native void tracepointInt(String name, int payload);
 
 /**
+ * Insert a tracepoint with a payload consisting of two integers.
+ *
+ * @param name
+ *The name assigned to this event. For best performance, this
+ *should be a statically-defined String, or a literal.
+ * @param payload1
+ *The first int payload
+ * @param payload2
+ *The second int payload
+ */
+public static native void
+tracepointIntInt(String name, int payload1, int payload2);
+
+/**
  * Insert a tracepoint with a payload of type Long
  *
  * @param name
@@ -68,6 +82,20 @@ public abstract class LTTngUst {
 public static native void tracepointLong(String name, long payload);
 
 /**
+ * Insert a tracepoint with a payload consisting of two longs.
+ *
+ * @param name
+ *The name assigned to this event. For best performance, this
+ *should be a statically-defined String, or a literal.
+ * @param payload1
+ *The first long payload
+ * @param payload2
+ *The second long payload
+ */
+public static native void
+tracepointLongLong(String name, long payload1, long payload2);
+
+/**
  * Insert a tracepoint with a String payload.
  *
  * @param name
diff --git a/liblttng-ust-java/lttng_ust_java.h 
b/liblttng-ust-java/lttng_ust_java.h
index 7cdbea5..7a8b391 100644
--- a/liblttng-ust-java/lttng_ust_java.h
+++ b/liblttng-ust-java/lttng_ust_java.h
@@ -32,6 +32,15 @@ TRACEPOINT_EVENT(lttng_ust_java, int_event,
)
 )
 
+TRACEPOINT_EVENT(lttng_ust_java, int_int_event,
+   TP_ARGS(const char *, name, int, payload1, int, payload2),
+   TP_FIELDS(
+   ctf_string(name, name)
+   ctf_integer(int, int_payload1, payload1)
+   ctf_integer(int, int_payload2, payload2)
+   )
+)
+
 TRACEPOINT_EVENT(lttng_ust_java, long_event,
TP_ARGS(const char *, name, long, payload),
TP_FIELDS(
@@ -40,6 +49,15 @@ TRACEPOINT_EVENT(lttng_ust_java, long_event,