rx: Make lock-free call data explicit
[openafs.git] / src / rx / rx_call.h
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #ifndef OPENAFS_RX_CALL_H
11 #define OPENAFS_RX_CALL_H 1
12
13 /*
14  * The following fields are accessed while the call is unlocked.
15  * These fields are used by the application thread to marshall
16  * and unmarshall RPC data. The only time they may be changed by
17  * other threads is when the RX_CALL_IOVEC_WAIT flag is set
18  *
19  * NOTE: Ensure that this structure is padded to a double word boundary
20  * to avoid problems with other threads accessing items stored beside it
21  * in the call structure
22  */
23 struct rx_call_appl {
24     struct opr_queue iovq;      /* readv/writev packet queue */
25     u_short nLeft;              /* Number bytes left in first receive packet */
26     u_short curvec;             /* current iovec in currentPacket */
27     u_short curlen;             /* bytes remaining in curvec */
28     u_short nFree;              /* Number bytes free in last send packet */
29     struct rx_packet *currentPacket;    /* Current packet being assembled or being read */
30     char *curpos;               /* current position in curvec */
31     int mode;                   /* Mode of call */
32     int padding;                /* Pad to double word */
33 };
34
35 /* Call structure:  only instantiated for active calls and dallying
36  * server calls.  The permanent call state (i.e. the call number as
37  * well as state shared with other calls associated with this
38  * connection) is maintained in the connection structure. */
39
40
41 #ifdef KDUMP_RX_LOCK
42 struct rx_call_rx_lock {
43 #else
44 struct rx_call {
45 #endif
46     struct opr_queue entry;     /* Call can be on various queues (one-at-a-time) */
47     struct opr_queue tq;        /* Transmit packet queue */
48     struct opr_queue rq;        /* Receive packet queue */
49     struct rx_call_appl app;    /* Data private to the application thread */
50     u_char channel;             /* Index of call, within connection */
51     u_char state;               /* Current call state as defined below */
52 #ifdef  RX_ENABLE_LOCKS
53     afs_kmutex_t lock;          /* lock covers data as well as mutexes. */
54     afs_kmutex_t *call_queue_lock;      /* points to lock for queue we're on,
55                                          * if any. */
56     afs_kcondvar_t cv_twind;
57     afs_kcondvar_t cv_rq;
58     afs_kcondvar_t cv_tq;
59 #endif
60 #ifdef KDUMP_RX_LOCK
61     struct rx_connection_rx_lock *conn; /* Parent connection for call */
62 #else
63     struct rx_connection *conn; /* Parent connection for this call */
64 #endif
65     afs_uint32 *callNumber;     /* Pointer to call number field within connection */
66     afs_uint32 flags;           /* Some random flags */
67     u_char localStatus;         /* Local user status sent out of band */
68     u_char remoteStatus;        /* Remote user status received out of band */
69     afs_int32 error;            /* Error condition for this call */
70     afs_uint32 timeout;         /* High level timeout for this call */
71     afs_uint32 rnext;           /* Next sequence number expected to be read by rx_ReadData */
72     afs_uint32 rprev;           /* Previous packet received; used for deciding what the next packet to be received should be, in order to decide whether a negative acknowledge should be sent */
73     afs_uint32 rwind;           /* The receive window:  the peer must not send packets with sequence numbers >= rnext+rwind */
74     afs_uint32 tfirst;          /* First unacknowledged transmit packet number */
75     afs_uint32 tnext;           /* Next transmit sequence number to use */
76     afs_uint32 tprev;           /* Last packet that we saw an ack for */
77     u_short twind;              /* The transmit window:  we cannot assign a sequence number to a packet >= tfirst + twind */
78     u_short cwind;              /* The congestion window */
79     u_short nSoftAcked;         /* Number soft acked transmit packets */
80     u_short nextCwind;          /* The congestion window after recovery */
81     u_short nCwindAcks;         /* Number acks received at current cwind */
82     u_short ssthresh;           /* The slow start threshold */
83     u_short nDgramPackets;      /* Packets per AFS 3.5 jumbogram */
84     u_short nAcks;              /* The number of consecutive acks */
85     u_short nNacks;             /* Number packets acked that follow the
86                                  * first negatively acked packet */
87     u_short nSoftAcks;          /* The number of delayed soft acks */
88     u_short nHardAcks;          /* The number of delayed hard acks */
89     u_short congestSeq;         /* Peer's congestion sequence counter */
90     int rtt;
91     int rtt_dev;
92     struct clock rto;           /* The round trip timeout calculated for this call */
93     struct rxevent *resendEvent;        /* If this is non-Null, there is a retransmission event pending */
94     struct rxevent *timeoutEvent;       /* If this is non-Null, then there is an overall timeout for this call */
95     struct rxevent *keepAliveEvent;     /* Scheduled periodically in active calls to keep call alive */
96     struct rxevent *growMTUEvent;      /* Scheduled periodically in active calls to discover true maximum MTU */
97     struct rxevent *delayedAckEvent;    /* Scheduled after all packets are received to send an ack if a reply or new call is not generated soon */
98     struct clock delayedAckTime;        /* Time that next delayed ack was scheduled  for */
99     struct rxevent *delayedAbortEvent;  /* Scheduled to throttle looping client */
100     int abortCode;              /* error code from last RPC */
101     int abortCount;             /* number of times last error was sent */
102     u_int lastSendTime;         /* Last time a packet was sent on this call */
103     u_int lastReceiveTime;      /* Last time a packet was received for this call */
104     u_int lastSendData;         /* Last time a nonping was sent on this call */
105     void (*arrivalProc) (struct rx_call * call, void * mh, int index);  /* Procedure to call when reply is received */
106     void *arrivalProcHandle;    /* Handle to pass to replyFunc */
107     int arrivalProcArg;         /* Additional arg to pass to reply Proc */
108     afs_uint32 lastAcked;       /* last packet "hard" acked by receiver */
109     afs_uint32 startWait;       /* time server began waiting for input data/send quota */
110     struct clock traceWait;     /* time server began waiting for input data/send quota */
111     struct clock traceStart;    /* time the call started running */
112     u_short MTU;                /* size of packets currently sending */
113 #ifdef RX_ENABLE_LOCKS
114     short refCount;             /* Used to keep calls from disappearring
115                                  * when we get them from a queue. (rx_refcnt_lock) */
116 #endif                          /* RX_ENABLE_LOCKS */
117 /* Call refcount modifiers */
118 #define RX_CALL_REFCOUNT_BEGIN  0       /* GetCall/NewCall/EndCall */
119 #define RX_CALL_REFCOUNT_RESEND 1       /* resend event */
120 #define RX_CALL_REFCOUNT_DELAY  2       /* delayed ack */
121 #define RX_CALL_REFCOUNT_ALIVE  3       /* keep alive event */
122 #define RX_CALL_REFCOUNT_PACKET 4       /* waiting for packets. */
123 #define RX_CALL_REFCOUNT_SEND   5       /* rxi_Send */
124 #define RX_CALL_REFCOUNT_ABORT  7       /* delayed abort */
125 #define RX_CALL_REFCOUNT_MTU    8       /* grow mtu event */
126 #define RX_CALL_REFCOUNT_MAX    9       /* array size. */
127 #ifdef RX_REFCOUNT_CHECK
128     short refCDebug[RX_CALL_REFCOUNT_MAX];
129 #endif                          /* RX_REFCOUNT_CHECK */
130
131     /*
132      * iov, iovNBytes, iovMax, and iovNext are set in rxi_ReadvProc()
133      * and adjusted by rxi_FillReadVec().  iov does not own the buffers
134      * it refers to.  The buffers belong to the packets stored in iovq.
135      * Only one call to rx_ReadvProc() can be active at a time.
136      */
137
138     int iovNBytes;              /* byte count for current iovec */
139     int iovMax;                 /* number elements in current iovec */
140     int iovNext;                /* next entry in current iovec */
141     struct iovec *iov;          /* current iovec */
142
143     struct clock queueTime;     /* time call was queued */
144     struct clock startTime;     /* time call was started */
145     afs_uint64 bytesSent;       /* Number bytes sent */
146     afs_uint64 bytesRcvd;       /* Number bytes received */
147     u_short tqWaiters;
148
149     struct rx_packet *xmitList[RX_MAXACKS]; /* Can't xmit more than we ack */
150                                 /* Protected by setting RX_CALL_TQ_BUSY */
151 #ifdef RXDEBUG_PACKET
152     u_short tqc;                /* packet count in tq */
153     u_short rqc;                /* packet count in rq */
154     u_short iovqc;              /* packet count in iovq */
155
156 #ifdef KDUMP_RX_LOCK
157     struct rx_call_rx_lock *allNextp;
158 #else
159     struct rx_call *allNextp;
160 #endif
161     afs_uint32 call_id;
162 #endif
163 #ifdef AFS_RXERRQ_ENV
164     int neterr_gen;
165 #endif
166 };
167
168 /* Only include this once, even when re-loading for kdump. */
169 #ifndef _CALL_REF_DEFINED_
170 #define _CALL_REF_DEFINED_
171
172 #ifdef RX_ENABLE_LOCKS
173
174 # define CALL_HOLD(call, type) do { \
175                                 MUTEX_ENTER(&rx_refcnt_mutex); \
176                                 CALL_HOLD_R(call, type); \
177                                 MUTEX_EXIT(&rx_refcnt_mutex); \
178                               } while(0)
179 # define CALL_RELE(call, type) do { \
180                                 MUTEX_ENTER(&rx_refcnt_mutex); \
181                                 CALL_RELE_R(call, type); \
182                                 MUTEX_EXIT(&rx_refcnt_mutex); \
183                               } while(0)
184
185 #ifdef RX_REFCOUNT_CHECK
186 /* RX_REFCOUNT_CHECK is used to test for call refcount leaks by event
187  * type.
188  */
189 extern int rx_callHoldType;
190 #define CALL_HOLD_R(call, type) do { \
191                                  call->refCount++; \
192                                  call->refCDebug[type]++; \
193                                  if (call->refCDebug[type] > 50)  {\
194                                      rx_callHoldType = type; \
195                                      osi_Panic("Huge call refCount"); \
196                                                                } \
197                              } while (0)
198 #define CALL_RELE_R(call, type) do { \
199                                  call->refCount--; \
200                                  call->refCDebug[type]--; \
201                                  if (call->refCDebug[type] > 50) {\
202                                      rx_callHoldType = type; \
203                                      osi_Panic("Negative call refCount"); \
204                                                               } \
205                              } while (0)
206 #else /* RX_REFCOUNT_CHECK */
207 #define CALL_HOLD_R(call, type)          call->refCount++
208 #define CALL_RELE_R(call, type)  call->refCount--
209 #endif /* RX_REFCOUNT_CHECK */
210
211 #else /* RX_ENABLE_LOCKS */
212 #define CALL_HOLD(call, type)
213 #define CALL_RELE(call, type)
214 #define CALL_RELE_R(call, type)
215 #endif /* RX_ENABLE_LOCKS */
216
217 #endif /* _CALL_REF_DEFINED_ */
218
219 #endif