Index: freeDiameter/cnxctx.c
===================================================================
--- freeDiameter/cnxctx.c	(revision 423)
+++ freeDiameter/cnxctx.c	(revision 454)
@@ -464,4 +464,5 @@
 {
 	CHECK_PARAMS_DO( conn, return 0 );
+	fd_cpu_flush_cache();
 	return conn->cc_status & CC_STATUS_TLS;
 }
@@ -545,4 +546,5 @@
 	
 	/* Mark the error */
+	fd_cpu_flush_cache();
 	conn->cc_status |= CC_STATUS_ERROR;
 	
@@ -553,5 +555,5 @@
 		conn->cc_status |= CC_STATUS_SIGNALED;
 	}
-	
+	fd_cpu_flush_cache();
 	return;
 fatal:
@@ -581,4 +583,5 @@
 	/* Handle special case of timeout */
 	if ((ret < 0) && (errno == EAGAIN)) {
+		fd_cpu_flush_cache();
 		if (! (conn->cc_status & CC_STATUS_CLOSING))
 			goto again; /* don't care, just ignore */
@@ -607,4 +610,5 @@
 	/* Handle special case of timeout */
 	if ((ret < 0) && (errno == EAGAIN)) {
+		fd_cpu_flush_cache();
 		if (! (conn->cc_status & CC_STATUS_CLOSING))
 			goto again; /* don't care, just ignore */
@@ -725,4 +729,5 @@
 	
 	do {
+		fd_cpu_flush_cache();
 		CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, NULL, &buf, &bufsz, &event, &conn->cc_status), goto fatal );
 		if (event == FDEVP_CNX_ERROR) {
@@ -796,4 +801,5 @@
 			switch (ret) {
 				case GNUTLS_E_REHANDSHAKE: 
+					fd_cpu_flush_cache();
 					if (!(conn->cc_status & CC_STATUS_CLOSING))
 						CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
@@ -807,4 +813,5 @@
 				case GNUTLS_E_AGAIN:
 				case GNUTLS_E_INTERRUPTED:
+					fd_cpu_flush_cache();
 					if (!(conn->cc_status & CC_STATUS_CLOSING))
 						goto again;
@@ -840,4 +847,5 @@
 			switch (ret) {
 				case GNUTLS_E_REHANDSHAKE: 
+					fd_cpu_flush_cache();
 					if (!(conn->cc_status & CC_STATUS_CLOSING))
 						CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
@@ -851,4 +859,5 @@
 				case GNUTLS_E_AGAIN:
 				case GNUTLS_E_INTERRUPTED:
+					fd_cpu_flush_cache();
 					if (!(conn->cc_status & CC_STATUS_CLOSING))
 						goto again;
@@ -1235,4 +1244,5 @@
 
 	/* Mark the connection as protected from here, so that the gnutls credentials will be freed */
+	fd_cpu_flush_cache();
 	conn->cc_status |= CC_STATUS_TLS;
 
@@ -1359,4 +1369,5 @@
 	TRACE_ENTRY("%p %p %zd", conn, buf, len);
 	do {
+		fd_cpu_flush_cache();
 		if (conn->cc_status & CC_STATUS_TLS) {
 			CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent),  );
@@ -1392,4 +1403,5 @@
 				/* Send the buffer over all other streams */
 				uint16_t str;
+				fd_cpu_flush_cache();
 				if (conn->cc_status & CC_STATUS_TLS) {
 					for ( str=1; str < conn->cc_sctp_para.pairs; str++) {
@@ -1474,4 +1486,5 @@
 	CHECK_PARAMS_DO(conn, return);
 	
+	fd_cpu_flush_cache();
 	conn->cc_status |= CC_STATUS_CLOSING;
 	
Index: freeDiameter/p_ce.c
===================================================================
--- freeDiameter/p_ce.c	(revision 403)
+++ freeDiameter/p_ce.c	(revision 454)
@@ -613,4 +613,5 @@
 	
 	/* Are we doing an election ? */
+	fd_cpu_flush_cache();
 	if (peer->p_hdr.info.runtime.pir_state == STATE_WAITCNXACK_ELEC) {
 		if (election_result(peer)) {
@@ -661,4 +662,5 @@
 	
 	/* If the state is not WAITCEA, just discard the message */
+	fd_cpu_flush_cache();
 	if (req || (peer->p_hdr.info.runtime.pir_state != STATE_WAITCEA)) {
 		if (*msg) {
@@ -922,4 +924,5 @@
 int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid)
 {
+	fd_cpu_flush_cache();
 	switch (peer->p_hdr.info.runtime.pir_state) {
 		case STATE_CLOSED:
Index: freeDiameter/p_dp.c
===================================================================
--- freeDiameter/p_dp.c	(revision 403)
+++ freeDiameter/p_dp.c	(revision 454)
@@ -114,4 +114,5 @@
 	} else {
 		/* We received a DPA */
+		fd_cpu_flush_cache();
 		if (peer->p_hdr.info.runtime.pir_state != STATE_CLOSING) {
 			TRACE_DEBUG(INFO, "Ignoring DPA received in state %s", STATE_STR(peer->p_hdr.info.runtime.pir_state));
Index: freeDiameter/p_dw.c
===================================================================
--- freeDiameter/p_dw.c	(revision 258)
+++ freeDiameter/p_dw.c	(revision 454)
@@ -123,4 +123,5 @@
 	
 	/* If we are in REOPEN state, increment the counter */
+	fd_cpu_flush_cache();
 	if (peer->p_hdr.info.runtime.pir_state == STATE_REOPEN) {
 		peer->p_flags.pf_reopen_cnt += 1;
Index: freeDiameter/p_expiry.c
===================================================================
--- freeDiameter/p_expiry.c	(revision 78)
+++ freeDiameter/p_expiry.c	(revision 454)
@@ -61,4 +61,5 @@
 			struct fd_peer * peer = (struct fd_peer *)li;
 			
+			fd_cpu_flush_cache();
 			if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE)
 				continue;
Index: freeDiameter/p_out.c
===================================================================
--- freeDiameter/p_out.c	(revision 258)
+++ freeDiameter/p_out.c	(revision 454)
@@ -143,4 +143,5 @@
 	CHECK_PARAMS( msg && *msg && (cnx || (peer && peer->p_cnxctx)));
 	
+	fd_cpu_flush_cache();
 	if (peer && (peer->p_hdr.info.runtime.pir_state == STATE_OPEN)) {
 		/* Normal case: just queue for the out thread to pick it up */
Index: freeDiameter/p_psm.c
===================================================================
--- freeDiameter/p_psm.c	(revision 403)
+++ freeDiameter/p_psm.c	(revision 454)
@@ -184,4 +184,5 @@
 	TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state));
 	CHECK_PARAMS( CHECK_PEER(peer) );
+	fd_cpu_flush_cache();
 	old = peer->p_hdr.info.runtime.pir_state;
 	if (old == new_state)
@@ -194,4 +195,5 @@
 	
 	peer->p_hdr.info.runtime.pir_state = new_state;
+	fd_cpu_flush_cache();
 	
 	if (old == STATE_OPEN) {
@@ -251,4 +253,5 @@
 {
 	/* Move to CLOSED state: failover messages, stop OUT thread, unlink peer from active list */
+	fd_cpu_flush_cache();
 	if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) {
 		CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ );
@@ -281,4 +284,5 @@
 	CHECK_PARAMS_DO( CHECK_PEER(peer), return );
 	peer->p_hdr.info.runtime.pir_state = STATE_ZOMBIE;
+	fd_cpu_flush_cache();
 	return;
 }
@@ -306,5 +310,5 @@
 	/* The state machine starts in CLOSED state */
 	peer->p_hdr.info.runtime.pir_state = STATE_CLOSED;
-	
+
 	/* Wait that the PSM are authorized to start in the daemon */
 	CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end );
@@ -709,4 +713,5 @@
 			peer->p_hdr.info.pi_diamid);
 	pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
+	fd_cpu_flush_cache();
 	peer->p_psm = (pthread_t)NULL;
 	pthread_detach(pthread_self());
@@ -742,4 +747,5 @@
 	CHECK_PARAMS( CHECK_PEER(peer) );
 	
+	fd_cpu_flush_cache();
 	if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) {
 		CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, reason) );
Index: freeDiameter/peers.c
===================================================================
--- freeDiameter/peers.c	(revision 403)
+++ freeDiameter/peers.c	(revision 454)
@@ -279,4 +279,5 @@
 		struct fd_peer * peer = (struct fd_peer *)li;
 		
+		fd_cpu_flush_cache();
 		if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) {
 			CHECK_FCT_DO( fd_psm_terminate(peer, "REBOOTING"), /* continue */ );
@@ -306,4 +307,5 @@
 		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
 			struct fd_peer * peer = (struct fd_peer *)li;
+			fd_cpu_flush_cache();
 			if (peer->p_hdr.info.runtime.pir_state == STATE_ZOMBIE) {
 				li = li->prev; /* to avoid breaking the loop */
@@ -462,4 +464,5 @@
 	} else {
 		/* Check if the peer is in zombie state */
+		fd_cpu_flush_cache();
 		if (peer->p_hdr.info.runtime.pir_state == STATE_ZOMBIE) {
 			/* Re-activate the peer */
Index: freeDiameter/routing_dispatch.c
===================================================================
--- freeDiameter/routing_dispatch.c	(revision 403)
+++ freeDiameter/routing_dispatch.c	(revision 454)
@@ -815,4 +815,5 @@
 		/* Find the peer corresponding to this name */
 		CHECK_FCT( fd_peer_getbyid( qry_src, (void *) &peer ) );
+		fd_cpu_flush_cache();
 		if ((!peer) || (peer->p_hdr.info.runtime.pir_state != STATE_OPEN)) {
 			TRACE_DEBUG(INFO, "Unable to forward answer message to peer '%s', deleted or not in OPEN state.", qry_src);
@@ -934,4 +935,5 @@
 		CHECK_FCT( fd_peer_getbyid( c->diamid, (void *)&peer ) );
 
+		fd_cpu_flush_cache();
 		if (peer && (peer->p_hdr.info.runtime.pir_state == STATE_OPEN)) {
 			/* Send to this one */
Index: freeDiameter/sctps.c
===================================================================
--- freeDiameter/sctps.c	(revision 403)
+++ freeDiameter/sctps.c	(revision 454)
@@ -87,4 +87,5 @@
 	
 	do {
+		fd_cpu_flush_cache();
 		CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event, &conn->cc_status), goto fatal );
 		switch (event) {
@@ -171,4 +172,5 @@
 	CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
 	
+	fd_cpu_flush_cache();
 	CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len, &ctx->parent->cc_status), /* errno is already set */ return -1 );
 	
@@ -620,4 +622,5 @@
 	/* End all TLS sessions, in series (not as efficient as paralel, but simpler) */
 	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+		fd_cpu_flush_cache();
 		if ( ! (conn->cc_status & CC_STATUS_ERROR)) {
 			CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
Index: include/freeDiameter/freeDiameter.h
===================================================================
--- include/freeDiameter/freeDiameter.h	(revision 447)
+++ include/freeDiameter/freeDiameter.h	(revision 454)
@@ -228,5 +228,5 @@
 	struct {
 		
-		enum peer_state	pir_state;	/* Current state of the peer in the state machine */
+		enum peer_state	pir_state;	/* Current state of the peer in the state machine. fd_cpu_flush_cache() might be useful before reading. */
 		
 		char * 		pir_realm;	/* The received realm in CER/CEA. */
@@ -252,4 +252,5 @@
 	struct fd_list	pi_endpoints;	/* Endpoint(s) of the remote peer (configured, discovered, or advertized). list of struct fd_endpoint. DNS resolved if empty. */
 };
+
 
 struct peer_hdr {
Index: include/freeDiameter/libfreeDiameter.h
===================================================================
--- include/freeDiameter/libfreeDiameter.h	(revision 453)
+++ include/freeDiameter/libfreeDiameter.h	(revision 454)
@@ -569,4 +569,12 @@
 }
 
+/* Force flushing the cache of a CPU before reading a shared memory area (use only for atomic reads such as int and void*) */
+extern pthread_mutex_t fd_cpu_mtx_dummy; /* only for the macro bellow, so that we have reasonably fresh pir_state value when needed */
+#define fd_cpu_flush_cache() {				\
+	(void)pthread_mutex_lock(&fd_cpu_mtx_dummy);	\
+	(void)pthread_mutex_unlock(&fd_cpu_mtx_dummy);	\
+}
+
+
 /*************
  Cancelation cleanup handlers for common objects 
Index: libfreeDiameter/init.c
===================================================================
--- libfreeDiameter/init.c	(revision 258)
+++ libfreeDiameter/init.c	(revision 454)
@@ -36,4 +36,7 @@
 #include "libfD.h"
 
+/* Only for CPU cache flush */
+pthread_mutex_t fd_cpu_mtx_dummy = PTHREAD_MUTEX_INITIALIZER;
+
 /* Initialize library variables and threads */
 int fd_lib_init(int support_signals)
