rx: Make lock-free call data explicit
[openafs.git] / src / rx / rx_call.h
index 8bc50b3..7179c1e 100644 (file)
 #ifndef OPENAFS_RX_CALL_H
 #define OPENAFS_RX_CALL_H 1
 
+/*
+ * The following fields are accessed while the call is unlocked.
+ * These fields are used by the application thread to marshall
+ * and unmarshall RPC data. The only time they may be changed by
+ * other threads is when the RX_CALL_IOVEC_WAIT flag is set
+ *
+ * NOTE: Ensure that this structure is padded to a double word boundary
+ * to avoid problems with other threads accessing items stored beside it
+ * in the call structure
+ */
+struct rx_call_appl {
+    struct opr_queue iovq;     /* readv/writev packet queue */
+    u_short nLeft;             /* Number bytes left in first receive packet */
+    u_short curvec;            /* current iovec in currentPacket */
+    u_short curlen;            /* bytes remaining in curvec */
+    u_short nFree;             /* Number bytes free in last send packet */
+    struct rx_packet *currentPacket;   /* Current packet being assembled or being read */
+    char *curpos;              /* current position in curvec */
+    int mode;                  /* Mode of call */
+    int padding;               /* Pad to double word */
+};
+
 /* Call structure:  only instantiated for active calls and dallying
  * server calls.  The permanent call state (i.e. the call number as
  * well as state shared with other calls associated with this
  * connection) is maintained in the connection structure. */
 
+
 #ifdef KDUMP_RX_LOCK
 struct rx_call_rx_lock {
 #else
 struct rx_call {
 #endif
-    struct rx_queue queue_item_header; /* Call can be on various queues (one-at-a-time) */
-    struct rx_queue tq;                /* Transmit packet queue */
-    struct rx_queue rq;                /* Receive packet queue */
-    /*
-     * The following fields are accessed while the call is unlocked.
-     * These fields are used by the caller/server thread to marshall
-     * and unmarshall RPC data. The only time they may be changed by
-     * other threads is when the RX_CALL_IOVEC_WAIT flag is set.
-     *
-     * NOTE: Be sure that these fields start and end on a double
-     *       word boundary. Otherwise threads that are changing
-     *       adjacent fields will cause problems.
-     */
-    struct rx_queue iovq;      /* readv/writev packet queue */
-    u_short nLeft;             /* Number bytes left in first receive packet */
-    u_short curvec;            /* current iovec in currentPacket */
-    u_short curlen;            /* bytes remaining in curvec */
-    u_short nFree;             /* Number bytes free in last send packet */
-    struct rx_packet *currentPacket;   /* Current packet being assembled or being read */
-    char *curpos;              /* current position in curvec */
-    /*
-     * End of fields accessed with call unlocked
-     */
+    struct opr_queue entry;    /* Call can be on various queues (one-at-a-time) */
+    struct opr_queue tq;       /* Transmit packet queue */
+    struct opr_queue rq;       /* Receive packet queue */
+    struct rx_call_appl app;   /* Data private to the application thread */
     u_char channel;            /* Index of call, within connection */
     u_char state;              /* Current call state as defined below */
-    u_char mode;               /* Current mode of a call in ACTIVE state */
 #ifdef RX_ENABLE_LOCKS
     afs_kmutex_t lock;         /* lock covers data as well as mutexes. */
     afs_kmutex_t *call_queue_lock;     /* points to lock for queue we're on,
@@ -118,9 +121,9 @@ struct rx_call {
 #define RX_CALL_REFCOUNT_ALIVE  3      /* keep alive event */
 #define RX_CALL_REFCOUNT_PACKET 4      /* waiting for packets. */
 #define RX_CALL_REFCOUNT_SEND   5      /* rxi_Send */
-#define RX_CALL_REFCOUNT_ACKALL 6      /* rxi_AckAll */
 #define RX_CALL_REFCOUNT_ABORT  7      /* delayed abort */
-#define RX_CALL_REFCOUNT_MAX    8      /* array size. */
+#define RX_CALL_REFCOUNT_MTU    8       /* grow mtu event */
+#define RX_CALL_REFCOUNT_MAX    9      /* array size. */
 #ifdef RX_REFCOUNT_CHECK
     short refCDebug[RX_CALL_REFCOUNT_MAX];
 #endif                         /* RX_REFCOUNT_CHECK */
@@ -139,8 +142,8 @@ struct rx_call {
 
     struct clock queueTime;    /* time call was queued */
     struct clock startTime;    /* time call was started */
-    afs_hyper_t bytesSent;     /* Number bytes sent */
-    afs_hyper_t bytesRcvd;     /* Number bytes received */
+    afs_uint64 bytesSent;      /* Number bytes sent */
+    afs_uint64 bytesRcvd;      /* Number bytes received */
     u_short tqWaiters;
 
     struct rx_packet *xmitList[RX_MAXACKS]; /* Can't xmit more than we ack */
@@ -157,6 +160,9 @@ struct rx_call {
 #endif
     afs_uint32 call_id;
 #endif
+#ifdef AFS_RXERRQ_ENV
+    int neterr_gen;
+#endif
 };
 
 /* Only include this once, even when re-loading for kdump. */
@@ -164,12 +170,24 @@ struct rx_call {
 #define _CALL_REF_DEFINED_
 
 #ifdef RX_ENABLE_LOCKS
+
+# define CALL_HOLD(call, type) do { \
+                               MUTEX_ENTER(&rx_refcnt_mutex); \
+                               CALL_HOLD_R(call, type); \
+                               MUTEX_EXIT(&rx_refcnt_mutex); \
+                             } while(0)
+# define CALL_RELE(call, type) do { \
+                               MUTEX_ENTER(&rx_refcnt_mutex); \
+                               CALL_RELE_R(call, type); \
+                               MUTEX_EXIT(&rx_refcnt_mutex); \
+                             } while(0)
+
 #ifdef RX_REFCOUNT_CHECK
 /* RX_REFCOUNT_CHECK is used to test for call refcount leaks by event
  * type.
  */
 extern int rx_callHoldType;
-#define CALL_HOLD(call, type) do { \
+#define CALL_HOLD_R(call, type) do { \
                                 call->refCount++; \
                                 call->refCDebug[type]++; \
                                 if (call->refCDebug[type] > 50)  {\
@@ -177,7 +195,7 @@ extern int rx_callHoldType;
                                     osi_Panic("Huge call refCount"); \
                                                               } \
                             } while (0)
-#define CALL_RELE(call, type) do { \
+#define CALL_RELE_R(call, type) do { \
                                 call->refCount--; \
                                 call->refCDebug[type]--; \
                                 if (call->refCDebug[type] > 50) {\
@@ -186,13 +204,14 @@ extern int rx_callHoldType;
                                                              } \
                             } while (0)
 #else /* RX_REFCOUNT_CHECK */
-#define CALL_HOLD(call, type)   call->refCount++
-#define CALL_RELE(call, type)   call->refCount--
+#define CALL_HOLD_R(call, type)         call->refCount++
+#define CALL_RELE_R(call, type)         call->refCount--
 #endif /* RX_REFCOUNT_CHECK */
 
 #else /* RX_ENABLE_LOCKS */
 #define CALL_HOLD(call, type)
 #define CALL_RELE(call, type)
+#define CALL_RELE_R(call, type)
 #endif /* RX_ENABLE_LOCKS */
 
 #endif /* _CALL_REF_DEFINED_ */