Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_hpts.c
Show First 20 Lines • Show All 508 Lines • ▼ Show 20 Lines | |||||
* This function relies on the fact that the hpts always holds a | * This function relies on the fact that the hpts always holds a | ||||
* reference on the inpcb while the segment is on the hptsi wheel and | * reference on the inpcb while the segment is on the hptsi wheel and | ||||
* in the input queue. | * in the input queue. | ||||
* | * | ||||
*/ | */ | ||||
static int | static int | ||||
tcp_hptsi_lock_inpinfo(struct inpcb *inp, struct tcpcb **tpp) | tcp_hptsi_lock_inpinfo(struct inpcb *inp, struct tcpcb **tpp) | ||||
{ | { | ||||
struct tcp_function_block *tfb; | |||||
struct tcpcb *tp; | |||||
void *ptr; | |||||
/* Try the easy way. */ | |||||
if (INP_INFO_TRY_RLOCK(&V_tcbinfo)) | |||||
return (0); | |||||
/* | |||||
* OK, let's try the hard way. We'll save the function pointer block | |||||
* to make sure that doesn't change while we aren't holding the | |||||
* lock. | |||||
*/ | |||||
tp = *tpp; | |||||
tfb = tp->t_fb; | |||||
ptr = tp->t_fb_ptr; | |||||
INP_WUNLOCK(inp); | |||||
INP_INFO_RLOCK(&V_tcbinfo); | |||||
INP_WLOCK(inp); | |||||
/* If the session went away, return an error. */ | |||||
if ((inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) || | |||||
(inp->inp_flags2 & INP_FREED)) { | |||||
*tpp = NULL; | |||||
return (1); | |||||
} | |||||
/* | |||||
* If the function block or stack-specific data block changed, | |||||
* report an error. | |||||
*/ | |||||
tp = intotcpcb(inp); | |||||
if ((tp->t_fb != tfb) && (tp->t_fb_ptr != ptr)) { | |||||
*tpp = NULL; | |||||
return (1); | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
tcp_wakehpts(struct tcp_hpts_entry *hpts) | tcp_wakehpts(struct tcp_hpts_entry *hpts) | ||||
{ | { | ||||
HPTS_MTX_ASSERT(hpts); | HPTS_MTX_ASSERT(hpts); | ||||
▲ Show 20 Lines • Show All 1,405 Lines • Show Last 20 Lines |