Browse code

- tcp fixes/atomic_t switch

Andrei Pelinescu-Onciul authored on 02/11/2006 22:55:56
Showing 5 changed files
... ...
@@ -67,7 +67,7 @@ MAIN_NAME=ser
67 67
 VERSION = 0
68 68
 PATCHLEVEL = 10
69 69
 SUBLEVEL =   99
70
-EXTRAVERSION = -dev55-tm_fixes
70
+EXTRAVERSION = -dev56-tm_fixes
71 71
 
72 72
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
73 73
 			$(SUBLEVEL) )
... ...
@@ -40,6 +40,7 @@
40 40
 
41 41
 #include "ip_addr.h"
42 42
 #include "locking.h"
43
+#include "atomic_ops.h"
43 44
 
44 45
 
45 46
 #define TCP_CON_MAX_ALIASES 4 /* maximum number of port aliases */
... ...
@@ -123,7 +124,7 @@ struct tcp_connection{
123 123
 	           reply-ing*/
124 124
 	struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/
125 125
 	struct tcp_req req; /* request data */
126
-	volatile int refcnt;
126
+	atomic_t refcnt;
127 127
 	enum sip_protos type; /* PROTO_TCP or a protocol over it, e.g. TLS */
128 128
 	int flags; /* connection related flags */
129 129
 	enum tcp_conn_states state; /* connection state */
... ...
@@ -142,6 +143,9 @@ struct tcp_connection{
142 142
 
143 143
 
144 144
 
145
+#define tcpconn_ref(c) atomic_inc(&((c)->refcnt))
146
+#define tcpconn_put(c) atomic_dec(&((c)->refcnt))
147
+
145 148
 
146 149
 #define init_tcp_req( r) \
147 150
 	do{ \
... ...
@@ -69,6 +69,8 @@
69 69
  *  2006-02-06  better tcp_max_connections checks, tcp_connections_no moved to
70 70
  *              shm (andrei)
71 71
  *  2006-04-12  tcp_send() changed to use struct dest_info (andrei)
72
+ *  2006-11-02  switched to atomic ops for refcnt, locking improvements 
73
+ *               (andrei)
72 74
  */
73 75
 
74 76
 
... ...
@@ -415,7 +417,7 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
415 415
 	
416 416
 	c->rcv.src_su=*su;
417 417
 	
418
-	c->refcnt=0;
418
+	atomic_set(&c->refcnt, 0);
419 419
 	su2ip_addr(&c->rcv.src_ip, su);
420 420
 	c->rcv.src_port=su_getport(su);
421 421
 	c->rcv.bind_address=ba;
... ...
@@ -522,25 +524,22 @@ error:
522 522
 
523 523
 struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
524 524
 {
525
-	unsigned hash;
526 525
 
527 526
 	if (c){
527
+		c->id_hash=tcp_id_hash(c->id);
528
+		c->con_aliases[0].hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port);
528 529
 		TCPCONN_LOCK;
529 530
 		/* add it at the begining of the list*/
530
-		hash=tcp_id_hash(c->id);
531
-		c->id_hash=hash;
532
-		tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev);
533
-		
534
-		hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port);
531
+		tcpconn_listadd(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
535 532
 		/* set the first alias */
536 533
 		c->con_aliases[0].port=c->rcv.src_port;
537
-		c->con_aliases[0].hash=hash;
538 534
 		c->con_aliases[0].parent=c;
539
-		tcpconn_listadd(tcpconn_aliases_hash[hash], &c->con_aliases[0],
540
-						next, prev);
535
+		tcpconn_listadd(tcpconn_aliases_hash[c->con_aliases[0].hash],
536
+							&c->con_aliases[0], next, prev);
541 537
 		c->aliases++;
542 538
 		TCPCONN_UNLOCK;
543
-		DBG("tcpconn_add: hashes: %d, %d\n", hash, c->id_hash);
539
+		DBG("tcpconn_add: hashes: %d, %d\n", c->con_aliases[0].hash,
540
+												c->id_hash);
544 541
 		return c;
545 542
 	}else{
546 543
 		LOG(L_CRIT, "tcpconn_add: BUG: null connection pointer\n");
... ...
@@ -634,7 +633,7 @@ struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
634 634
 	TCPCONN_LOCK;
635 635
 	c=_tcpconn_find(id, ip, port);
636 636
 	if (c){ 
637
-			c->refcnt++;
637
+			atomic_inc(&c->refcnt);
638 638
 			c->timeout=get_ticks()+timeout;
639 639
 	}
640 640
 	TCPCONN_UNLOCK;
... ...
@@ -704,24 +703,6 @@ error_sec:
704 704
 
705 705
 
706 706
 
707
-void tcpconn_ref(struct tcp_connection* c)
708
-{
709
-	TCPCONN_LOCK;
710
-	c->refcnt++; /* FIXME: atomic_dec */
711
-	TCPCONN_UNLOCK;
712
-}
713
-
714
-
715
-
716
-void tcpconn_put(struct tcp_connection* c)
717
-{
718
-	TCPCONN_LOCK;
719
-	c->refcnt--; /* FIXME: atomic_dec */
720
-	TCPCONN_UNLOCK;
721
-}
722
-
723
-
724
-
725 707
 /* finds a tcpconn & sends on it
726 708
  * uses the dst members to, proto (TCP|TLS) and id
727 709
  * returns: number of bytes written (>=0) on success
... ...
@@ -768,8 +749,7 @@ no_id:
768 768
 				LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
769 769
 				return -1;
770 770
 			}
771
-			c->refcnt++; /* safe to do it w/o locking, it's not yet
772
-							available to the rest of the world */
771
+			atomic_set(&c->refcnt, 1); /* ref. only from here for now */
773 772
 			fd=c->s;
774 773
 			
775 774
 			/* send the new tcpconn to "tcp main" */
... ...
@@ -811,8 +791,8 @@ get_fd:
811 811
 				LOG(L_CRIT, "BUG: tcp_send: get_fd: got different connection:"
812 812
 						"  %p (id= %d, refcnt=%d state=%d != "
813 813
 						"  %p (id= %d, refcnt=%d state=%d (n=%d)\n",
814
-						  c,   c->id,   c->refcnt,   c->state,
815
-						  tmp, tmp->id, tmp->refcnt, tmp->state, n
814
+						  c,   c->id,   atomic_get(&c->refcnt),   c->state,
815
+						  tmp, tmp->id, atomic_get(&tmp->refcnt), tmp->state, n
816 816
 				   );
817 817
 				n=-1; /* fail */
818 818
 				goto end;
... ...
@@ -963,8 +943,7 @@ static void tcpconn_destroy(struct tcp_connection* tcpconn)
963 963
 	int fd;
964 964
 
965 965
 	TCPCONN_LOCK; /*avoid races w/ tcp_send*/
966
-	tcpconn->refcnt--;
967
-	if (tcpconn->refcnt==0){ 
966
+	if (atomic_dec_and_test(&tcpconn->refcnt)){ 
968 967
 		DBG("tcpconn_destroy: destroying connection %p, flags %04x\n",
969 968
 				tcpconn, tcpconn->flags);
970 969
 		fd=tcpconn->s;
... ...
@@ -1209,7 +1188,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
1209 1209
 			io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn);
1210 1210
 			tcpconn->flags&=~F_CONN_REMOVED;
1211 1211
 			DBG("handle_tcp_child: CONN_RELEASE  %p refcnt= %d\n", 
1212
-											tcpconn, tcpconn->refcnt);
1212
+							tcpconn, atomic_get(&tcpconn->refcnt));
1213 1213
 			break;
1214 1214
 		case CONN_ERROR:
1215 1215
 		case CONN_DESTROY:
... ...
@@ -1480,8 +1459,8 @@ static inline int handle_new_connect(struct socket_info* si)
1480 1480
 		tcpconn->flags&=~F_CONN_REMOVED;
1481 1481
 		tcpconn_add(tcpconn);
1482 1482
 #else
1483
-		tcpconn->refcnt++; /* safe, not yet available to the
1484
-							  outside world */
1483
+		atomic_set(&tcpconn->refcnt, 1); /* safe, not yet available to the
1484
+											outside world */
1485 1485
 		tcpconn_add(tcpconn);
1486 1486
 		DBG("handle_new_connect: new connection: %p %d flags: %04x\n",
1487 1487
 			tcpconn, tcpconn->s, tcpconn->flags);
... ...
@@ -1623,7 +1602,8 @@ static inline void tcpconn_timeout(int force)
1623 1623
 		c=tcpconn_id_hash[h];
1624 1624
 		while(c){
1625 1625
 			next=c->id_next;
1626
-			if (force ||((c->refcnt==0) && ((int)(ticks-c->timeout)>=0))){
1626
+			if (force ||((atomic_get(&c->refcnt)==0) &&
1627
+						((int)(ticks-c->timeout)>=0))){
1627 1628
 				if (!force)
1628 1629
 					DBG("tcpconn_timeout: timeout for hash=%d - %p"
1629 1630
 							" (%d > %d)\n", h, c, ticks, c->timeout);
... ...
@@ -1633,7 +1613,7 @@ static inline void tcpconn_timeout(int force)
1633 1633
 					tls_close(c, fd);
1634 1634
 #endif
1635 1635
 				_tcpconn_rm(c);
1636
-				if ((fd>0)&&(c->refcnt==0)) {
1636
+				if ((fd>0)&&(atomic_get(&c->refcnt)==0)) {
1637 1637
 					if (!(c->flags & F_CONN_REMOVED)){
1638 1638
 						io_watch_del(&io_h, fd, -1, IO_FD_CLOSING);
1639 1639
 						c->flags|=F_CONN_REMOVED;
... ...
@@ -754,7 +754,7 @@ void tcp_receive_loop(int unix_sock)
754 754
 					LOG(L_CRIT, "BUG: tcp_receive_loop: duplicate"
755 755
 							" connection received: %p, id %d, fd %d, refcnt %d"
756 756
 							" state %d (n=%d)\n", con, con->id, con->fd,
757
-							con->refcnt, con->state, n);
757
+							atomic_get(&con->refcnt), con->state, n);
758 758
 					resp=CONN_ERROR;
759 759
 					release_tcpconn(con, resp, unix_sock);
760 760
 					goto skip; /* try to recover */
... ...
@@ -767,7 +767,8 @@ skip:
767 767
 				c_next=con->c_next; /* safe for removing*/
768 768
 #ifdef EXTRA_DEBUG
769 769
 				DBG("tcp receive: list fd=%d, id=%d, timeout=%d, refcnt=%d\n",
770
-						con->fd, con->id, con->timeout, con->refcnt);
770
+						con->fd, con->id, con->timeout,
771
+						atomic_get(&con->refcnt));
771 772
 #endif
772 773
 				if (con->state<0){
773 774
 					/* S_CONN_BAD or S_CONN_ERROR, remove it */
... ...
@@ -869,7 +870,7 @@ again:
869 869
 				LOG(L_CRIT, "BUG: tcp_receive: handle_io: duplicate"
870 870
 							" connection received: %p, id %d, fd %d, refcnt %d"
871 871
 							" state %d (n=%d)\n", con, con->id, con->fd,
872
-							con->refcnt, con->state, n);
872
+							atomic_get(&con->refcnt), con->state, n);
873 873
 				release_tcpconn(con, CONN_ERROR, tcpmain_sock);
874 874
 				break; /* try to recover */
875 875
 			}
... ...
@@ -34,9 +34,6 @@
34 34
 
35 35
 /* "public" functions*/
36 36
 
37
-struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port, 
38
-									int timeout);
39
-void tcpconn_put(struct tcp_connection* c);
40 37
 int tcp_send(struct dest_info* dst, char* buf, unsigned len);
41 38
 
42 39
 int tcpconn_add_alias(int id, int port, int proto);