optimized queue unwrapping on arm
diff --git a/aos/linux_code/ipc_lib/queue.cc b/aos/linux_code/ipc_lib/queue.cc
index 67faf5b..81af416 100644
--- a/aos/linux_code/ipc_lib/queue.cc
+++ b/aos/linux_code/ipc_lib/queue.cc
@@ -65,6 +65,17 @@
 #endif
 };
 
+inline int RawQueue::index_add1(int index) {
+  // Doing it this way instead of with % is more efficient on ARM.
+  int r = index + 1;
+  assert(index <= data_length_);
+  if (r == data_length_) {
+    return 0;
+  } else {
+    return r;
+  }
+}
+
 void RawQueue::DecrementMessageReferenceCount(const void *msg) {
   MessageHeader *header = MessageHeader::Get(msg);
   __atomic_sub_fetch(&header->ref_count, 1, __ATOMIC_RELAXED);
@@ -287,7 +298,7 @@
 
     int new_end;
     while (true) {
-      new_end = (data_end_ + 1) % data_length_;
+      new_end = index_add1(data_end_);
       // If there is room in the queue right now.
       if (new_end != data_start_) break;
       if (options & kNonBlock) {
@@ -302,7 +313,7 @@
         }
         // Avoid leaking the message that we're going to overwrite.
         DecrementMessageReferenceCount(data_[data_start_]);
-        data_start_ = (data_start_ + 1) % data_length_;
+        data_start_ = index_add1(data_start_);
       } else {  // kBlock
         if (kWriteDebug) {
           printf("queue: going to wait for writable_ of %p\n", this);
@@ -409,7 +420,7 @@
         }
         // This loop pulls each message out of the buffer.
         const int pos = data_start_;
-        data_start_ = (data_start_ + 1) % data_length_;
+        data_start_ = index_add1(data_start_);
         // If this is the last one.
         if (data_start_ == data_end_) {
           if (kReadDebug) {
@@ -430,7 +441,7 @@
     if (options & kPeek) {
       IncrementMessageReferenceCount(msg);
     } else {
-      data_start_ = (data_start_ + 1) % data_length_;
+      data_start_ = index_add1(data_start_);
     }
   }
   ReadCommonEnd();
diff --git a/aos/linux_code/ipc_lib/queue.h b/aos/linux_code/ipc_lib/queue.h
index 255bc63..d4d2609 100644
--- a/aos/linux_code/ipc_lib/queue.h
+++ b/aos/linux_code/ipc_lib/queue.h
@@ -1,6 +1,8 @@
 #ifndef AOS_LINUX_CODE_IPC_LIB_QUEUE_H_
 #define AOS_LINUX_CODE_IPC_LIB_QUEUE_H_
 
+#include <assert.h>
+
 #include "aos/linux_code/ipc_lib/shared_mem.h"
 #include "aos/common/mutex.h"
 #include "aos/common/condition.h"
@@ -123,8 +125,11 @@
  private:
   struct MessageHeader;
 
+  // Adds 1 to the given index and handles wrapping correctly.
+  int index_add1(int index);
+
   bool is_readable() { return data_end_ != data_start_; }
-  bool is_writable() { return ((data_end_ + 1) % data_length_) != data_start_; }
+  bool is_writable() { return index_add1(data_end_) != data_start_; }
 
   // These next 4 allow finding the right one.
   const char *name_;