http://cvs.opensolaris.org/source/xref/on/usr/src/uts/common/io/mac/mac.c,
910 /*
911 * Unregister a receive function for this mac. This removes the function
912 * from the list of receive functions for this mac.
913 */
914 void
915 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh)
916 {
917 mac_impl_t *mip = (mac_impl_t *)mh;
918 mac_rx_fn_t *mrfp = (mac_rx_fn_t *)mrh;
919 mac_rx_fn_t **pp;
920 mac_rx_fn_t *p;
921
922 /*
923 * Search the ’rx’ callback list for the function closure.
924 */
925 rw_enter(&(mip->mi_rx_lock), RW_WRITER);
926 for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) {
927 if (p == mrfp)
928 break;
929 }
930 ASSERT(p != NULL);
931
932 /* Remove it from the list. */
933 *pp = p->mrf_nextp;
934 kmem_free(mrfp, sizeof (mac_rx_fn_t));
935 rw_exit(&(mip->mi_rx_lock));
936 }
3. 结合代码,我们更容易看出死锁的时序,如下面描述:
(1) 线程B, dladm调用aggr_grp_rem_ports并成功获得lg_lock,以RW_WRITER的写方式
(2) 线程A, TCP报文到达聚合,网卡中断处理程序调用序列调用mac_rx,成功获得mi_rx_lock,以RW_READER方式
(3) 线程A, TCP处理完毕需要返回ACK报文,mac_rx继续调用aggr_m_tx并试图获得lg_lock作为RW_READER, 但是现在lg_lock正在被线程B在步骤(1)以RW_WRITER所持有,所以线程A阻塞
(4) 线程B,继续执行。aggr_grp_rem_ports调用mac_rx_remove并试图获得mi_rx_lock,以RW_WRITER方式, 但现在mi_rx_lock正在被线程A以RW_READER方式持有, 所以线程B也阻塞在这里
(5) 死锁发生
910 /*
911 * Unregister a receive function for this mac. This removes the function
912 * from the list of receive functions for this mac.
913 */
914 void
915 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh)
916 {
917 mac_impl_t *mip = (mac_impl_t *)mh;
918 mac_rx_fn_t *mrfp = (mac_rx_fn_t *)mrh;
919 mac_rx_fn_t **pp;
920 mac_rx_fn_t *p;
921
922 /*
923 * Search the ’rx’ callback list for the function closure.
924 */
925 rw_enter(&(mip->mi_rx_lock), RW_WRITER);
926 for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) {
927 if (p == mrfp)
928 break;
929 }
930 ASSERT(p != NULL);
931
932 /* Remove it from the list. */
933 *pp = p->mrf_nextp;
934 kmem_free(mrfp, sizeof (mac_rx_fn_t));
935 rw_exit(&(mip->mi_rx_lock));
936 }
3. 结合代码,我们更容易看出死锁的时序,如下面描述:
(1) 线程B, dladm调用aggr_grp_rem_ports并成功获得lg_lock,以RW_WRITER的写方式
(2) 线程A, TCP报文到达聚合,网卡中断处理程序调用序列调用mac_rx,成功获得mi_rx_lock,以RW_READER方式
(3) 线程A, TCP处理完毕需要返回ACK报文,mac_rx继续调用aggr_m_tx并试图获得lg_lock作为RW_READER, 但是现在lg_lock正在被线程B在步骤(1)以RW_WRITER所持有,所以线程A阻塞
(4) 线程B,继续执行。aggr_grp_rem_ports调用mac_rx_remove并试图获得mi_rx_lock,以RW_WRITER方式, 但现在mi_rx_lock正在被线程A以RW_READER方式持有, 所以线程B也阻塞在这里
(5) 死锁发生