Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / system / local_data_pipe_unittest.cc
index 6d747bd..eb9eddd 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <string.h>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "mojo/system/data_pipe.h"
 #include "mojo/system/waiter.h"
@@ -24,9 +24,10 @@ TEST(LocalDataPipeTest, Creation) {
   // Create using default options.
   {
     // Get default options.
-    MojoCreateDataPipeOptions default_options = { 0 };
-    EXPECT_EQ(MOJO_RESULT_OK,
-              DataPipe::ValidateCreateOptions(NULL, &default_options));
+    MojoCreateDataPipeOptions default_options = {0};
+    EXPECT_EQ(
+        MOJO_RESULT_OK,
+        DataPipe::ValidateCreateOptions(NullUserPointer(), &default_options));
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(default_options));
     dp->ProducerClose();
     dp->ConsumerClose();
@@ -35,42 +36,45 @@ TEST(LocalDataPipeTest, Creation) {
   // Create using non-default options.
   {
     const MojoCreateDataPipeOptions options = {
-      kSizeOfOptions,  // |struct_size|.
-      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-      1,  // |element_num_bytes|.
-      1000  // |capacity_num_bytes|.
+        kSizeOfOptions,                           // |struct_size|.
+        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+        1,                                        // |element_num_bytes|.
+        1000                                      // |capacity_num_bytes|.
     };
-    MojoCreateDataPipeOptions validated_options = { 0 };
+    MojoCreateDataPipeOptions validated_options = {0};
     EXPECT_EQ(MOJO_RESULT_OK,
-              DataPipe::ValidateCreateOptions(&options, &validated_options));
+              DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                              &validated_options));
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
     dp->ProducerClose();
     dp->ConsumerClose();
   }
   {
     const MojoCreateDataPipeOptions options = {
-      kSizeOfOptions,  // |struct_size|.
-      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-      4,  // |element_num_bytes|.
-      4000  // |capacity_num_bytes|.
+        kSizeOfOptions,                           // |struct_size|.
+        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+        4,                                        // |element_num_bytes|.
+        4000                                      // |capacity_num_bytes|.
     };
-    MojoCreateDataPipeOptions validated_options = { 0 };
+    MojoCreateDataPipeOptions validated_options = {0};
     EXPECT_EQ(MOJO_RESULT_OK,
-              DataPipe::ValidateCreateOptions(&options, &validated_options));
+              DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                              &validated_options));
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
     dp->ProducerClose();
     dp->ConsumerClose();
   }
   {
     const MojoCreateDataPipeOptions options = {
-      kSizeOfOptions,  // |struct_size|.
-      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
-      7,  // |element_num_bytes|.
-      7000000  // |capacity_num_bytes|.
+        kSizeOfOptions,                                  // |struct_size|.
+        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
+        7,                                               // |element_num_bytes|.
+        7000000  // |capacity_num_bytes|.
     };
-    MojoCreateDataPipeOptions validated_options = { 0 };
+    MojoCreateDataPipeOptions validated_options = {0};
     EXPECT_EQ(MOJO_RESULT_OK,
-              DataPipe::ValidateCreateOptions(&options, &validated_options));
+              DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                              &validated_options));
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
     dp->ProducerClose();
     dp->ConsumerClose();
@@ -78,14 +82,15 @@ TEST(LocalDataPipeTest, Creation) {
   // Default capacity.
   {
     const MojoCreateDataPipeOptions options = {
-      kSizeOfOptions,  // |struct_size|.
-      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
-      100,  // |element_num_bytes|.
-      0  // |capacity_num_bytes|.
+        kSizeOfOptions,                                  // |struct_size|.
+        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
+        100,                                             // |element_num_bytes|.
+        0  // |capacity_num_bytes|.
     };
-    MojoCreateDataPipeOptions validated_options = { 0 };
+    MojoCreateDataPipeOptions validated_options = {0};
     EXPECT_EQ(MOJO_RESULT_OK,
-              DataPipe::ValidateCreateOptions(&options, &validated_options));
+              DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                              &validated_options));
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
     dp->ProducerClose();
     dp->ConsumerClose();
@@ -94,74 +99,86 @@ TEST(LocalDataPipeTest, Creation) {
 
 TEST(LocalDataPipeTest, SimpleReadWrite) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    1000 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      1000 * sizeof(int32_t)                    // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
-  int32_t elements[10] = { 0 };
+  int32_t elements[10] = {0};
   uint32_t num_bytes = 0;
 
   // Try reading; nothing there yet.
   num_bytes = static_cast<uint32_t>(arraysize(elements) * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
-            dp->ConsumerReadData(elements, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_SHOULD_WAIT,
+      dp->ConsumerReadData(
+          UserPointer<void>(elements), MakeUserPointer(&num_bytes), false));
 
   // Query; nothing there yet.
   num_bytes = 0;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   // Discard; nothing there yet.
   num_bytes = static_cast<uint32_t>(5u * sizeof(elements[0]));
   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
-            dp->ConsumerDiscardData(&num_bytes, false));
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), false));
 
   // Read with invalid |num_bytes|.
   num_bytes = sizeof(elements[0]) + 1;
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            dp->ConsumerReadData(elements, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_INVALID_ARGUMENT,
+      dp->ConsumerReadData(
+          UserPointer<void>(elements), MakeUserPointer(&num_bytes), false));
 
   // Write two elements.
   elements[0] = 123;
   elements[1] = 456;
   num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerWriteData(elements, &num_bytes, false));
+            dp->ProducerWriteData(UserPointer<const void>(elements),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   // It should have written everything (even without "all or none").
   EXPECT_EQ(2u * sizeof(elements[0]), num_bytes);
 
   // Query.
   num_bytes = 0;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(2 * sizeof(elements[0]), num_bytes);
 
   // Read one element.
   elements[0] = -1;
   elements[1] = -1;
   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerReadData(
+          UserPointer<void>(elements), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(1u * sizeof(elements[0]), num_bytes);
   EXPECT_EQ(123, elements[0]);
   EXPECT_EQ(-1, elements[1]);
 
   // Query.
   num_bytes = 0;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(1 * sizeof(elements[0]), num_bytes);
 
   // Try to read two elements, with "all or none".
   elements[0] = -1;
   elements[1] = -1;
   num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerReadData(elements, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ConsumerReadData(
+          UserPointer<void>(elements), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(-1, elements[0]);
   EXPECT_EQ(-1, elements[1]);
 
@@ -169,13 +186,16 @@ TEST(LocalDataPipeTest, SimpleReadWrite) {
   elements[0] = -1;
   elements[1] = -1;
   num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerReadData(
+          UserPointer<void>(elements), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(456, elements[0]);
   EXPECT_EQ(-1, elements[1]);
 
   // Query.
   num_bytes = 0;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   dp->ProducerClose();
@@ -190,53 +210,72 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
   // are strict maximums. This is not guaranteed by the API.
 
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    2 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      2 * sizeof(int32_t)                       // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
   Waiter waiter;
   uint32_t context = 0;
+  HandleSignalsState hss;
 
   // Never readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_FAILED_PRECONDITION,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Already writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34, &hss));
 
   // Write two elements.
-  int32_t elements[2] = { 123, 456 };
+  int32_t elements[2] = {123, 456};
   uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ProducerWriteData(UserPointer<const void>(elements),
+                                  MakeUserPointer(&num_bytes),
+                                  true));
   EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes);
 
   // Adding a waiter should now succeed.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, NULL));
   // And it shouldn't be writable yet.
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-  dp->ProducerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ProducerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Do it again.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78, NULL));
 
   // Read one element.
   elements[0] = -1;
   elements[1] = -1;
   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerReadData(
+          UserPointer<void>(elements), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
   EXPECT_EQ(123, elements[0]);
   EXPECT_EQ(-1, elements[1]);
@@ -244,13 +283,17 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
   // Waiting should now succeed.
   EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
   EXPECT_EQ(78u, context);
-  dp->ProducerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ProducerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Try writing, using a two-phase write.
   void* buffer = NULL;
   num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&buffer, &num_bytes, false));
+            dp->ProducerBeginWriteData(
+                MakeUserPointer(&buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_TRUE(buffer != NULL);
   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
 
@@ -261,39 +304,49 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
 
   // Add a waiter.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90, NULL));
 
   // Read one element, using a two-phase read.
   const void* read_buffer = NULL;
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerBeginReadData(
+          MakeUserPointer(&read_buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_TRUE(read_buffer != NULL);
   // Since we only read one element (after having written three in all), the
   // two-phase read should only allow us to read one. This checks an
   // implementation detail!
   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
   EXPECT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]);
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerEndReadData(
-                static_cast<uint32_t>(1u * sizeof(elements[0]))));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerEndReadData(static_cast<uint32_t>(1u * sizeof(elements[0]))));
 
   // Waiting should succeed.
   EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
   EXPECT_EQ(90u, context);
-  dp->ProducerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ProducerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Write one element.
   elements[0] = 123;
   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ProducerWriteData(UserPointer<const void>(elements),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
 
   // Add a waiter.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, NULL));
 
   // Close the consumer.
   dp->ConsumerClose();
@@ -301,107 +354,151 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
   // It should now be never-writable.
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context));
   EXPECT_EQ(12u, context);
-  dp->ProducerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ProducerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
 
   dp->ProducerClose();
 }
 
 TEST(LocalDataPipeTest, BasicConsumerWaiting) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    1000 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      1000 * sizeof(int32_t)                    // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   {
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
     Waiter waiter;
     uint32_t context = 0;
+    HandleSignalsState hss;
 
     // Never writable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_FAILED_PRECONDITION,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, &hss));
+    EXPECT_EQ(0u, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Not yet readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34));
+    ASSERT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, NULL));
     EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-    dp->ConsumerRemoveWaiter(&waiter);
+    hss = HandleSignalsState();
+    dp->ConsumerRemoveWaiter(&waiter, &hss);
+    EXPECT_EQ(0u, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Write two elements.
-    int32_t elements[2] = { 123, 456 };
+    int32_t elements[2] = {123, 456};
     uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerWriteData(elements, &num_bytes, true));
+              dp->ProducerWriteData(UserPointer<const void>(elements),
+                                    MakeUserPointer(&num_bytes),
+                                    true));
 
     // Should already be readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_ALREADY_EXISTS,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, &hss));
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Discard one element.
     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
-    EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true));
+    EXPECT_EQ(MOJO_RESULT_OK,
+              dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
 
     // Should still be readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_ALREADY_EXISTS,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss));
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Read one element.
     elements[0] = -1;
     elements[1] = -1;
     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
-    EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, true));
+    EXPECT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerReadData(
+            UserPointer<void>(elements), MakeUserPointer(&num_bytes), true));
     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
     EXPECT_EQ(456, elements[0]);
     EXPECT_EQ(-1, elements[1]);
 
     // Adding a waiter should now succeed.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90));
+    ASSERT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90, NULL));
 
     // Write one element.
     elements[0] = 789;
     elements[1] = -1;
     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerWriteData(elements, &num_bytes, true));
+              dp->ProducerWriteData(UserPointer<const void>(elements),
+                                    MakeUserPointer(&num_bytes),
+                                    true));
 
     // Waiting should now succeed.
     EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
     EXPECT_EQ(90u, context);
-    dp->ConsumerRemoveWaiter(&waiter);
+    hss = HandleSignalsState();
+    dp->ConsumerRemoveWaiter(&waiter, &hss);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Close the producer.
     dp->ProducerClose();
 
     // Should still be readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_ALREADY_EXISTS,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Read one element.
     elements[0] = -1;
     elements[1] = -1;
     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
-    EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, true));
+    EXPECT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerReadData(
+            UserPointer<void>(elements), MakeUserPointer(&num_bytes), true));
     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
     EXPECT_EQ(789, elements[0]);
     EXPECT_EQ(-1, elements[1]);
 
     // Should be never-readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_FAILED_PRECONDITION,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss));
+    EXPECT_EQ(0u, hss.satisfied_signals);
+    EXPECT_EQ(0u, hss.satisfiable_signals);
 
     dp->ConsumerClose();
   }
@@ -412,6 +509,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
     Waiter waiter;
     uint32_t context = 0;
+    HandleSignalsState hss;
 
     // Write two elements.
     int32_t* elements = NULL;
@@ -419,7 +517,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
     // Request room for three (but we'll only write two).
     uint32_t num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerBeginWriteData(&buffer, &num_bytes, true));
+              dp->ProducerBeginWriteData(
+                  MakeUserPointer(&buffer), MakeUserPointer(&num_bytes), true));
     EXPECT_TRUE(buffer != NULL);
     EXPECT_GE(num_bytes, static_cast<uint32_t>(3u * sizeof(elements[0])));
     elements = static_cast<int32_t*>(buffer);
@@ -431,15 +530,21 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
 
     // Should already be readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_ALREADY_EXISTS,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Read one element.
     // Request two in all-or-none mode, but only read one.
     const void* read_buffer = NULL;
     num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
-    EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerBeginReadData(&read_buffer, &num_bytes, true));
+    EXPECT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerBeginReadData(
+            MakeUserPointer(&read_buffer), MakeUserPointer(&num_bytes), true));
     EXPECT_TRUE(read_buffer != NULL);
     EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes);
     const int32_t* read_elements = static_cast<const int32_t*>(read_buffer);
@@ -450,15 +555,21 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
 
     // Should still be readable.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34));
+    hss = HandleSignalsState();
+    EXPECT_EQ(
+        MOJO_RESULT_ALREADY_EXISTS,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss));
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
     // Read one element.
     // Request three, but not in all-or-none mode.
     read_buffer = NULL;
     num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
-    EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerBeginReadData(&read_buffer, &num_bytes, false));
+    EXPECT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerBeginReadData(
+            MakeUserPointer(&read_buffer), MakeUserPointer(&num_bytes), false));
     EXPECT_TRUE(read_buffer != NULL);
     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
     read_elements = static_cast<const int32_t*>(read_buffer);
@@ -469,8 +580,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
 
     // Adding a waiter should now succeed.
     waiter.Init();
-    EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56));
+    ASSERT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, NULL));
 
     // Close the producer.
     dp->ProducerClose();
@@ -478,7 +590,10 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
     // Should be never-readable.
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context));
     EXPECT_EQ(56u, context);
-    dp->ConsumerRemoveWaiter(&waiter);
+    hss = HandleSignalsState();
+    dp->ConsumerRemoveWaiter(&waiter, &hss);
+    EXPECT_EQ(0u, hss.satisfied_signals);
+    EXPECT_EQ(0u, hss.satisfiable_signals);
 
     dp->ConsumerClose();
   }
@@ -487,72 +602,102 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
 // Tests that data pipes aren't writable/readable during two-phase writes/reads.
 TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    1000 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      1000 * sizeof(int32_t)                    // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
   Waiter waiter;
+  HandleSignalsState hss;
 
   // It should be writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   uint32_t num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
   void* write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_TRUE(write_ptr != NULL);
   EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t)));
 
   // At this point, it shouldn't be writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1, NULL));
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-  dp->ProducerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ProducerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // It shouldn't be readable yet either.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 2));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, NULL));
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-  dp->ConsumerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ConsumerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   static_cast<int32_t*>(write_ptr)[0] = 123;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerEndWriteData(
-                static_cast<uint32_t>(1u * sizeof(int32_t))));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerEndWriteData(static_cast<uint32_t>(1u * sizeof(int32_t))));
 
   // It should be writable again.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // And readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Start another two-phase write and check that it's readable even in the
   // middle of it.
   num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_TRUE(write_ptr != NULL);
   EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t)));
 
   // It should be readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // End the two-phase write without writing anything.
   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u));
@@ -560,30 +705,44 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
   // Start a two-phase read.
   num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
   const void* read_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerBeginReadData(
+          MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_TRUE(read_ptr != NULL);
   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(int32_t)), num_bytes);
 
   // At this point, it should still be writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // But not readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, NULL));
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-  dp->ConsumerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ConsumerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // End the two-phase read without reading anything.
   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u));
 
   // It should be readable again.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   dp->ProducerClose();
   dp->ConsumerClose();
@@ -592,82 +751,122 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
 // Test that a "may discard" data pipe is writable even when it's full.
 TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    1 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                                  // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),          // |element_num_bytes|.
+      1 * sizeof(int32_t)                              // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
   Waiter waiter;
+  HandleSignalsState hss;
 
   // Writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Not readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, NULL));
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-  dp->ConsumerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ConsumerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   uint32_t num_bytes = static_cast<uint32_t>(sizeof(int32_t));
   int32_t element = 123;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerWriteData(&element, &num_bytes, false));
+            dp->ProducerWriteData(UserPointer<const void>(&element),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes);
 
   // Still writable (even though it's full).
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Now readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Overwrite that element.
   num_bytes = static_cast<uint32_t>(sizeof(int32_t));
   element = 456;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerWriteData(&element, &num_bytes, false));
+            dp->ProducerWriteData(UserPointer<const void>(&element),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes);
 
   // Still writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // And still readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Read that element.
   num_bytes = static_cast<uint32_t>(sizeof(int32_t));
   element = 0;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerReadData(&element, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerReadData(
+          UserPointer<void>(&element), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes);
   EXPECT_EQ(456, element);
 
   // Still writable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6));
+  hss = HandleSignalsState();
+  EXPECT_EQ(
+      MOJO_RESULT_ALREADY_EXISTS,
+      dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // No longer readable.
   waiter.Init();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7));
+  ASSERT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, NULL));
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
-  dp->ConsumerRemoveWaiter(&waiter);
+  hss = HandleSignalsState();
+  dp->ConsumerRemoveWaiter(&waiter, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   dp->ProducerClose();
   dp->ConsumerClose();
@@ -680,31 +879,37 @@ void Seq(int32_t start, size_t count, int32_t* out) {
 
 TEST(LocalDataPipeTest, MayDiscard) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    10 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                                  // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),          // |element_num_bytes|.
+      10 * sizeof(int32_t)                             // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
-  int32_t buffer[100] = { 0 };
+  int32_t buffer[100] = {0};
   uint32_t num_bytes = 0;
 
   num_bytes = 20u * sizeof(int32_t);
   Seq(0, arraysize(buffer), buffer);
   // Try writing more than capacity. (This test relies on the implementation
   // enforcing the capacity strictly.)
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
 
   // Read half of what we wrote.
   num_bytes = 5u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
   int32_t expected_buffer[100];
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
@@ -716,7 +921,10 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Write a bit more than the space that's available.
   num_bytes = 8u * sizeof(int32_t);
   Seq(100, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(8u * sizeof(int32_t), num_bytes);
   // Internally, a circular buffer would now look like:
   //   100, 101, 102, 103, 104, 105, 106, 107, 8, 9
@@ -724,7 +932,9 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Read half of what's available.
   num_bytes = 5u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   expected_buffer[0] = 8;
@@ -739,7 +949,10 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Write one integer.
   num_bytes = 1u * sizeof(int32_t);
   Seq(200, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
   // Internally, a circular buffer would now look like:
   //   -, -, -, 103, 104, 105, 106, 107, 200, -
@@ -747,7 +960,10 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Write five more.
   num_bytes = 5u * sizeof(int32_t);
   Seq(300, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
   // Internally, a circular buffer would now look like:
   //   301, 302, 303, 304, 104, 105, 106, 107, 200, 300
@@ -755,7 +971,9 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Read it all.
   num_bytes = sizeof(buffer);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   expected_buffer[0] = 104;
@@ -777,8 +995,10 @@ TEST(LocalDataPipeTest, MayDiscard) {
 
   num_bytes = 0u;
   void* write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_TRUE(write_ptr != NULL);
   EXPECT_EQ(6u * sizeof(int32_t), num_bytes);
   Seq(400, 6, static_cast<int32_t*>(write_ptr));
@@ -790,8 +1010,10 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // mode.
   num_bytes = 6u * sizeof(int32_t);
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(4u * sizeof(int32_t), num_bytes);
   static_cast<int32_t*>(write_ptr)[0] = 500;
   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(1u * sizeof(int32_t)));
@@ -801,15 +1023,19 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Requesting a 10-element buffer in all-or-none mode fails at this point.
   num_bytes = 10u * sizeof(int32_t);
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
 
   // But requesting, say, a 5-element (up to 9, really) buffer should be okay.
   // It will discard two elements.
   num_bytes = 5u * sizeof(int32_t);
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
   // Only write 4 elements though.
   Seq(600, 4, static_cast<int32_t*>(write_ptr));
@@ -821,8 +1047,10 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // the internal buffer.
   num_bytes = 5u * sizeof(int32_t);
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
   // Only write 3 elements though.
   Seq(700, 3, static_cast<int32_t*>(write_ptr));
@@ -833,7 +1061,9 @@ TEST(LocalDataPipeTest, MayDiscard) {
   // Read everything.
   num_bytes = sizeof(buffer);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(8u * sizeof(int32_t), num_bytes);
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   expected_buffer[0] = 500;
@@ -852,14 +1082,15 @@ TEST(LocalDataPipeTest, MayDiscard) {
 
 TEST(LocalDataPipeTest, AllOrNone) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    10 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      10 * sizeof(int32_t)                      // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
@@ -867,36 +1098,44 @@ TEST(LocalDataPipeTest, AllOrNone) {
   uint32_t num_bytes = 20u * sizeof(int32_t);
   int32_t buffer[100];
   Seq(0, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
 
   // Should still be empty.
   num_bytes = ~0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   // Write some data.
   num_bytes = 5u * sizeof(int32_t);
   Seq(100, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
 
   // Half full.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
 
   // Too much.
   num_bytes = 6u * sizeof(int32_t);
   Seq(200, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
 
   // Try reading too much.
   num_bytes = 11u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerReadData(buffer, &num_bytes, true));
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   int32_t expected_buffer[100];
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
@@ -904,29 +1143,37 @@ TEST(LocalDataPipeTest, AllOrNone) {
   // Try discarding too much.
   num_bytes = 11u * sizeof(int32_t);
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerDiscardData(&num_bytes, true));
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
 
   // Just a little.
   num_bytes = 2u * sizeof(int32_t);
   Seq(300, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(2u * sizeof(int32_t), num_bytes);
 
   // Just right.
   num_bytes = 3u * sizeof(int32_t);
   Seq(400, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(3u * sizeof(int32_t), num_bytes);
 
   // Exactly full.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
 
   // Read half.
   num_bytes = 5u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   Seq(100, 5, expected_buffer);
@@ -936,23 +1183,25 @@ TEST(LocalDataPipeTest, AllOrNone) {
   num_bytes = 6u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerReadData(buffer, &num_bytes, true));
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
 
   // Try discarding too much again.
   num_bytes = 6u * sizeof(int32_t);
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerDiscardData(&num_bytes, true));
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
 
   // Discard a little.
   num_bytes = 2u * sizeof(int32_t);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(2u * sizeof(int32_t), num_bytes);
 
   // Three left.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(3u * sizeof(int32_t), num_bytes);
 
   // Close the producer, then test producer-closed cases.
@@ -962,19 +1211,22 @@ TEST(LocalDataPipeTest, AllOrNone) {
   num_bytes = 4u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            dp->ConsumerReadData(buffer, &num_bytes, true));
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
 
   // Try discarding too much; "failed precondition" again.
   num_bytes = 4u * sizeof(int32_t);
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            dp->ConsumerDiscardData(&num_bytes, true));
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
 
   // Read a little.
   num_bytes = 2u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(2u * sizeof(int32_t), num_bytes);
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   Seq(400, 2, expected_buffer);
@@ -982,12 +1234,13 @@ TEST(LocalDataPipeTest, AllOrNone) {
 
   // Discard the remaining element.
   num_bytes = 1u * sizeof(int32_t);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
 
   // Empty again.
   num_bytes = ~0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   dp->ConsumerClose();
@@ -995,14 +1248,15 @@ TEST(LocalDataPipeTest, AllOrNone) {
 
 TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    10 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                                  // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),          // |element_num_bytes|.
+      10 * sizeof(int32_t)                             // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
@@ -1010,25 +1264,35 @@ TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
   uint32_t num_bytes = 20u * sizeof(int32_t);
   int32_t buffer[100];
   Seq(0, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
 
   // Write some stuff.
   num_bytes = 5u * sizeof(int32_t);
   Seq(100, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
 
   // Write lots of stuff (discarding all but "104").
   num_bytes = 9u * sizeof(int32_t);
   Seq(200, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(9u * sizeof(int32_t), num_bytes);
 
   // Read one.
   num_bytes = 1u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
   int32_t expected_buffer[100];
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
@@ -1039,34 +1303,41 @@ TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
   num_bytes = 10u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerReadData(buffer, &num_bytes, true));
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
 
   // Try discarding too many.
   num_bytes = 10u * sizeof(int32_t);
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerDiscardData(&num_bytes, true));
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
 
   // Discard a bunch.
   num_bytes = 4u * sizeof(int32_t);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
 
   // Half full.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
 
   // Write as much as possible.
   num_bytes = 10u * sizeof(int32_t);
   Seq(300, arraysize(buffer), buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
 
   // Read everything.
   num_bytes = 10u * sizeof(int32_t);
   memset(buffer, 0xab, sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ConsumerReadData(
+                UserPointer<void>(buffer), MakeUserPointer(&num_bytes), true));
   memset(expected_buffer, 0xab, sizeof(expected_buffer));
   EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
   Seq(300, 10, expected_buffer);
@@ -1081,42 +1352,50 @@ TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
 
 TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    10 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      10 * sizeof(int32_t)                      // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
   // Try writing way too much (two-phase).
   uint32_t num_bytes = 20u * sizeof(int32_t);
   void* write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
 
   // Try writing an amount which isn't a multiple of the element size
   // (two-phase).
   COMPILE_ASSERT(sizeof(int32_t) > 1u, wow_int32_ts_have_size_1);
   num_bytes = 1u;
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_INVALID_ARGUMENT,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
 
   // Try reading way too much (two-phase).
   num_bytes = 20u * sizeof(int32_t);
   const void* read_ptr = NULL;
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true));
+            dp->ConsumerBeginReadData(
+                MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), true));
 
   // Write half (two-phase).
   num_bytes = 5u * sizeof(int32_t);
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
   // May provide more space than requested.
   EXPECT_GE(num_bytes, 5u * sizeof(int32_t));
   EXPECT_TRUE(write_ptr != NULL);
@@ -1128,46 +1407,54 @@ TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
   num_bytes = 1u;
   read_ptr = NULL;
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true));
+            dp->ConsumerBeginReadData(
+                MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), true));
 
   // Read one (two-phase).
   num_bytes = 1u * sizeof(int32_t);
   read_ptr = NULL;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true));
+            dp->ConsumerBeginReadData(
+                MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), true));
   EXPECT_GE(num_bytes, 1u * sizeof(int32_t));
   EXPECT_EQ(0, static_cast<const int32_t*>(read_ptr)[0]);
   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(1u * sizeof(int32_t)));
 
   // We should have four left, leaving room for six.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(4u * sizeof(int32_t), num_bytes);
 
   // Assuming a tight circular buffer of the specified capacity, we can't do a
   // two-phase write of six now.
   num_bytes = 6u * sizeof(int32_t);
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OUT_OF_RANGE,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), true));
 
   // Write six elements (simple), filling the buffer.
   num_bytes = 6u * sizeof(int32_t);
   int32_t buffer[100];
   Seq(100, 6, buffer);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerWriteData(
+          UserPointer<const void>(buffer), MakeUserPointer(&num_bytes), true));
   EXPECT_EQ(6u * sizeof(int32_t), num_bytes);
 
   // We have ten.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
 
   // But a two-phase read of ten should fail.
   num_bytes = 10u * sizeof(int32_t);
   read_ptr = NULL;
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true));
+            dp->ConsumerBeginReadData(
+                MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), true));
 
   // Close the producer.
   dp->ProducerClose();
@@ -1176,7 +1463,8 @@ TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
   num_bytes = 9u * sizeof(int32_t);
   read_ptr = NULL;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true));
+            dp->ConsumerBeginReadData(
+                MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), true));
   EXPECT_GE(num_bytes, 9u * sizeof(int32_t));
   EXPECT_EQ(1, static_cast<const int32_t*>(read_ptr)[0]);
   EXPECT_EQ(2, static_cast<const int32_t*>(read_ptr)[1]);
@@ -1193,7 +1481,8 @@ TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
   num_bytes = 2u * sizeof(int32_t);
   read_ptr = NULL;
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true));
+            dp->ConsumerBeginReadData(
+                MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), true));
 
   dp->ConsumerClose();
 }
@@ -1208,14 +1497,15 @@ TEST(LocalDataPipeTest, WrapAround) {
     test_data[i] = static_cast<unsigned char>(i);
 
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    1u,  // |element_num_bytes|.
-    100u  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      1u,                                       // |element_num_bytes|.
+      100u                                      // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
   // This test won't be valid if |ValidateCreateOptions()| decides to give the
   // pipe more space.
   ASSERT_EQ(100u, validated_options.capacity_num_bytes);
@@ -1225,14 +1515,18 @@ TEST(LocalDataPipeTest, WrapAround) {
   // Write 20 bytes.
   uint32_t num_bytes = 20u;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerWriteData(&test_data[0], &num_bytes, false));
+            dp->ProducerWriteData(UserPointer<const void>(&test_data[0]),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   EXPECT_EQ(20u, num_bytes);
 
   // Read 10 bytes.
-  unsigned char read_buffer[1000] = { 0 };
+  unsigned char read_buffer[1000] = {0};
   num_bytes = 10u;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerReadData(read_buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerReadData(
+          UserPointer<void>(read_buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(10u, num_bytes);
   EXPECT_EQ(0, memcmp(read_buffer, &test_data[0], 10u));
 
@@ -1242,7 +1536,9 @@ TEST(LocalDataPipeTest, WrapAround) {
   void* write_buffer_ptr = NULL;
   num_bytes = 0u;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_buffer_ptr, &num_bytes, false));
+            dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
+                                       MakeUserPointer(&num_bytes),
+                                       false));
   EXPECT_TRUE(write_buffer_ptr != NULL);
   EXPECT_EQ(80u, num_bytes);
   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u));
@@ -1251,7 +1547,9 @@ TEST(LocalDataPipeTest, WrapAround) {
   // 90 bytes.
   num_bytes = 200u;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerWriteData(&test_data[20], &num_bytes, false));
+            dp->ProducerWriteData(UserPointer<const void>(&test_data[20]),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   EXPECT_EQ(90u, num_bytes);
 
   // Check that a two-phase read can now only read (at most) 90 bytes. (This
@@ -1260,7 +1558,9 @@ TEST(LocalDataPipeTest, WrapAround) {
   const void* read_buffer_ptr = NULL;
   num_bytes = 0u;
   EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_buffer_ptr, &num_bytes, false));
+            dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
+                                      MakeUserPointer(&num_bytes),
+                                      false));
   EXPECT_TRUE(read_buffer_ptr != NULL);
   EXPECT_EQ(90u, num_bytes);
   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u));
@@ -1270,8 +1570,10 @@ TEST(LocalDataPipeTest, WrapAround) {
   num_bytes =
       static_cast<uint32_t>(arraysize(read_buffer) * sizeof(read_buffer[0]));
   memset(read_buffer, 0, num_bytes);
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerReadData(read_buffer, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerReadData(
+          UserPointer<void>(read_buffer), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(100u, num_bytes);
   EXPECT_EQ(0, memcmp(read_buffer, &test_data[10], 100u));
 
@@ -1286,14 +1588,15 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
   const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
 
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    1u,  // |element_num_bytes|.
-    1000u  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      1u,                                       // |element_num_bytes|.
+      1000u                                     // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   // Close producer first, then consumer.
   {
@@ -1302,20 +1605,26 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     // Write some data, so we'll have something to read.
     uint32_t num_bytes = kTestDataSize;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerWriteData(kTestData, &num_bytes, false));
+              dp->ProducerWriteData(UserPointer<const void>(kTestData),
+                                    MakeUserPointer(&num_bytes),
+                                    false));
     EXPECT_EQ(kTestDataSize, num_bytes);
 
     // Write it again, so we'll have something left over.
     num_bytes = kTestDataSize;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerWriteData(kTestData, &num_bytes, false));
+              dp->ProducerWriteData(UserPointer<const void>(kTestData),
+                                    MakeUserPointer(&num_bytes),
+                                    false));
     EXPECT_EQ(kTestDataSize, num_bytes);
 
     // Start two-phase write.
     void* write_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerBeginWriteData(&write_buffer_ptr, &num_bytes, false));
+              dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
+                                         MakeUserPointer(&num_bytes),
+                                         false));
     EXPECT_TRUE(write_buffer_ptr != NULL);
     EXPECT_GT(num_bytes, 0u);
 
@@ -1323,7 +1632,9 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     const void* read_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerBeginReadData(&read_buffer_ptr, &num_bytes, false));
+              dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
+                                        MakeUserPointer(&num_bytes),
+                                        false));
     EXPECT_TRUE(read_buffer_ptr != NULL);
     EXPECT_EQ(2u * kTestDataSize, num_bytes);
 
@@ -1338,7 +1649,9 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     read_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerBeginReadData(&read_buffer_ptr, &num_bytes, false));
+              dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
+                                        MakeUserPointer(&num_bytes),
+                                        false));
     EXPECT_TRUE(read_buffer_ptr != NULL);
     EXPECT_EQ(kTestDataSize, num_bytes);
 
@@ -1353,14 +1666,18 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     // Write some data, so we'll have something to read.
     uint32_t num_bytes = kTestDataSize;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerWriteData(kTestData, &num_bytes, false));
+              dp->ProducerWriteData(UserPointer<const void>(kTestData),
+                                    MakeUserPointer(&num_bytes),
+                                    false));
     EXPECT_EQ(kTestDataSize, num_bytes);
 
     // Start two-phase write.
     void* write_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerBeginWriteData(&write_buffer_ptr, &num_bytes, false));
+              dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
+                                         MakeUserPointer(&num_bytes),
+                                         false));
     EXPECT_TRUE(write_buffer_ptr != NULL);
     ASSERT_GT(num_bytes, kTestDataSize);
 
@@ -1368,7 +1685,9 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     const void* read_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerBeginReadData(&read_buffer_ptr, &num_bytes, false));
+              dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
+                                        MakeUserPointer(&num_bytes),
+                                        false));
     EXPECT_TRUE(read_buffer_ptr != NULL);
     EXPECT_EQ(kTestDataSize, num_bytes);
 
@@ -1385,13 +1704,17 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     // But trying to write should result in failure.
     num_bytes = kTestDataSize;
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ProducerWriteData(kTestData, &num_bytes, false));
+              dp->ProducerWriteData(UserPointer<const void>(kTestData),
+                                    MakeUserPointer(&num_bytes),
+                                    false));
 
     // As will trying to start another two-phase write.
     write_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ProducerBeginWriteData(&write_buffer_ptr, &num_bytes, false));
+              dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
+                                         MakeUserPointer(&num_bytes),
+                                         false));
 
     dp->ProducerClose();
   }
@@ -1405,7 +1728,9 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     void* write_buffer_ptr = NULL;
     uint32_t num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerBeginWriteData(&write_buffer_ptr, &num_bytes, false));
+              dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
+                                         MakeUserPointer(&num_bytes),
+                                         false));
     EXPECT_TRUE(write_buffer_ptr != NULL);
     ASSERT_GT(num_bytes, kTestDataSize);
 
@@ -1420,7 +1745,9 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     // Write some data, so we'll have something to read.
     uint32_t num_bytes = kTestDataSize;
     EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ProducerWriteData(kTestData, &num_bytes, false));
+              dp->ProducerWriteData(UserPointer<const void>(kTestData),
+                                    MakeUserPointer(&num_bytes),
+                                    false));
     EXPECT_EQ(kTestDataSize, num_bytes);
 
     // Close the producer.
@@ -1429,26 +1756,32 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
     // Read that data.
     char buffer[1000];
     num_bytes = static_cast<uint32_t>(sizeof(buffer));
-    EXPECT_EQ(MOJO_RESULT_OK,
-              dp->ConsumerReadData(buffer, &num_bytes, false));
+    EXPECT_EQ(
+        MOJO_RESULT_OK,
+        dp->ConsumerReadData(
+            UserPointer<void>(buffer), MakeUserPointer(&num_bytes), false));
     EXPECT_EQ(kTestDataSize, num_bytes);
     EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize));
 
     // A second read should fail.
     num_bytes = static_cast<uint32_t>(sizeof(buffer));
-    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ConsumerReadData(buffer, &num_bytes, false));
+    EXPECT_EQ(
+        MOJO_RESULT_FAILED_PRECONDITION,
+        dp->ConsumerReadData(
+            UserPointer<void>(buffer), MakeUserPointer(&num_bytes), false));
 
     // A two-phase read should also fail.
     const void* read_buffer_ptr = NULL;
     num_bytes = 0u;
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ConsumerBeginReadData(&read_buffer_ptr, &num_bytes, false));
+              dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
+                                        MakeUserPointer(&num_bytes),
+                                        false));
 
     // Ditto for discard.
     num_bytes = 10u;
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              dp->ConsumerDiscardData(&num_bytes, false));
+              dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), false));
 
     dp->ConsumerClose();
   }
@@ -1456,20 +1789,21 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
 
 TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
-    static_cast<uint32_t>(sizeof(int32_t)),  // |element_num_bytes|.
-    10 * sizeof(int32_t)  // |capacity_num_bytes|.
+      kSizeOfOptions,                           // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
+      static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|.
+      10 * sizeof(int32_t)                      // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
   // No data.
   uint32_t num_bytes = 1000u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   // Try "ending" a two-phase write when one isn't active.
@@ -1478,32 +1812,36 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
 
   // Still no data.
   num_bytes = 1000u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   // Try ending a two-phase write with an invalid amount (too much).
   num_bytes = 0u;
   void* write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            dp->ProducerEndWriteData(
-                num_bytes + static_cast<uint32_t>(sizeof(int32_t))));
+            dp->ProducerEndWriteData(num_bytes +
+                                     static_cast<uint32_t>(sizeof(int32_t))));
 
   // But the two-phase write still ended.
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, dp->ProducerEndWriteData(0u));
 
   // Still no data.
   num_bytes = 1000u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   // Try ending a two-phase write with an invalid amount (not a multiple of the
   // element size).
   num_bytes = 0u;
   write_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ProducerBeginWriteData(
+          MakeUserPointer(&write_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_GE(num_bytes, 1u);
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dp->ProducerEndWriteData(1u));
 
@@ -1512,17 +1850,20 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
 
   // Still no data.
   num_bytes = 1000u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(0u, num_bytes);
 
   // Now write some data, so we'll be able to try reading.
   int32_t element = 123;
   num_bytes = 1u * sizeof(int32_t);
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(&element, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ProducerWriteData(UserPointer<const void>(&element),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
 
   // One element available.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
 
   // Try "ending" a two-phase read when one isn't active.
@@ -1531,36 +1872,40 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
 
   // Still one element available.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
 
   // Try ending a two-phase read with an invalid amount (too much).
   num_bytes = 0u;
   const void* read_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerBeginReadData(
+          MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            dp->ConsumerEndReadData(
-                num_bytes + static_cast<uint32_t>(sizeof(int32_t))));
+            dp->ConsumerEndReadData(num_bytes +
+                                    static_cast<uint32_t>(sizeof(int32_t))));
 
   // Still one element available.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
 
   // Try ending a two-phase read with an invalid amount (not a multiple of the
   // element size).
   num_bytes = 0u;
   read_ptr = NULL;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerBeginReadData(
+          MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
   EXPECT_EQ(123, static_cast<const int32_t*>(read_ptr)[0]);
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dp->ConsumerEndReadData(1u));
 
   // Still one element available.
   num_bytes = 0u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes));
+  EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
   EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
 
   dp->ProducerClose();
@@ -1576,28 +1921,34 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
 // |ProducerWriteData()| then changes the data underneath the two-phase read.)
 TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
   const MojoCreateDataPipeOptions options = {
-    kSizeOfOptions,  // |struct_size|.
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
-    1,  // |element_num_bytes|.
-    2  // |capacity_num_bytes|.
+      kSizeOfOptions,                                  // |struct_size|.
+      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|.
+      1,                                               // |element_num_bytes|.
+      2                                                // |capacity_num_bytes|.
   };
-  MojoCreateDataPipeOptions validated_options = { 0 };
+  MojoCreateDataPipeOptions validated_options = {0};
   EXPECT_EQ(MOJO_RESULT_OK,
-            DataPipe::ValidateCreateOptions(&options, &validated_options));
+            DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
+                                            &validated_options));
 
   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
 
   // Write some elements.
-  char elements[2] = { 'a', 'b' };
+  char elements[2] = {'a', 'b'};
   uint32_t num_bytes = 2u;
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ProducerWriteData(UserPointer<const void>(elements),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
   EXPECT_EQ(2u, num_bytes);
 
   // Begin reading.
   const void* read_ptr = NULL;
   num_bytes = 2u;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerBeginReadData(
+          MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(2u, num_bytes);
   EXPECT_EQ('a', static_cast<const char*>(read_ptr)[0]);
   EXPECT_EQ('b', static_cast<const char*>(read_ptr)[1]);
@@ -1611,7 +1962,10 @@ TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
   //            dp->ProducerWriteData(elements, &num_bytes, false));
   // but we incorrectly think that the bytes being read are discardable. Letting
   // this through reveals the significant consequence.
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ProducerWriteData(UserPointer<const void>(elements),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
 
   // Check that our read buffer hasn't changed underneath us.
   EXPECT_EQ('a', static_cast<const char*>(read_ptr)[0]);
@@ -1621,13 +1975,18 @@ TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(2u));
 
   // Now writing should succeed.
-  EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, false));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dp->ProducerWriteData(UserPointer<const void>(elements),
+                                  MakeUserPointer(&num_bytes),
+                                  false));
 
   // And if we read, we should get the new values.
   read_ptr = NULL;
   num_bytes = 2u;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            dp->ConsumerBeginReadData(&read_ptr, &num_bytes, false));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      dp->ConsumerBeginReadData(
+          MakeUserPointer(&read_ptr), MakeUserPointer(&num_bytes), false));
   EXPECT_EQ(2u, num_bytes);
   EXPECT_EQ('x', static_cast<const char*>(read_ptr)[0]);
   EXPECT_EQ('y', static_cast<const char*>(read_ptr)[1]);