Now that tinc is multi-threaded, we need some form of synchronisation. For
now, there is a single mutex which we lock whenever we do something with global
data structures. The main thread, from which timer events are handled, is
always locked unless it is sleeping for the next event, the other threads
receive incoming I/O unlocked, and lock to process the received data.
In the future more fine-grained locking should be used, probably in the form of
rwlocks, or lockless algorithms (maybe RCU).
while(true) {
if(read_packet(&packet)) {
while(true) {
if(read_packet(&packet)) {
} else {
if(errno == EAGAIN || errno == EINTR) {
errno = 0;
} else {
if(errno == EAGAIN || errno == EINTR) {
errno = 0;
if(c->tcplen > *len)
break;
if(c->tcplen > *len)
break;
receive_tcppacket(c, reqbuf, c->tcplen);
receive_tcppacket(c, reqbuf, c->tcplen);
memmove(reqbuf, reqbuf, *len - c->tcplen);
*len -= c->tcplen;
memmove(reqbuf, reqbuf, *len - c->tcplen);
*len -= c->tcplen;
- if(!receive_request(c, reqbuf))
+ mutex_lock(&mutex);
+ bool success = receive_request(c, reqbuf);
+ mutex_unlock(&mutex);
+
+ if(!success)
return false;
memmove(reqbuf, end, *len - (end - reqbuf));
return false;
memmove(reqbuf, end, *len - (end - reqbuf));
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
+ if(!result) {
+ mutex_lock(&mutex);
+ mutex_unlock(&mutex);
+ } else {
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
"Error while connecting to %s (%s): %s",
c->name, c->hostname, sockstrerror(result));
closesocket(c->socket);
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
"Error while connecting to %s (%s): %s",
c->name, c->hostname, sockstrerror(result));
closesocket(c->socket);
do_outgoing_connection(c);
do_outgoing_connection(c);
while(true) {
if (!receive_meta(c)) {
terminate_connection(c, c->status.active);
while(true) {
if (!receive_meta(c)) {
terminate_connection(c, c->status.active);
+ mutex_unlock(&mutex);
+ usleep(1000000);
+ mutex_lock(&mutex);
+
struct event *event;
while((event = get_expired_event())) {
event->handler(event->data);
struct event *event;
while((event = get_expired_event())) {
event->handler(event->data);
#ifndef HAVE_MINGW
#define closesocket(s) close(s)
#ifndef HAVE_MINGW
#define closesocket(s) close(s)
-#else
-extern CRITICAL_SECTION mutex;
#endif /* __TINC_NET_H__ */
#endif /* __TINC_NET_H__ */
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
n = lookup_node_udp(&from);
if(!n) {
n = try_harder(&from, &pkt);
if(n)
update_node_udp(n, &from);
n = lookup_node_udp(&from);
if(!n) {
n = try_harder(&from, &pkt);
if(n)
update_node_udp(n, &from);
- else ifdebug(PROTOCOL) {
+ }
+
+ if(n) {
+ receive_udppacket(n, &pkt);
+ } else {
+ ifdebug(PROTOCOL) {
hostname = sockaddr2hostname(&from);
logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
free(hostname);
hostname = sockaddr2hostname(&from);
logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
free(hostname);
- receive_udppacket(n, &pkt);
connection_add(c);
c->allow_request = ID;
connection_add(c);
c->allow_request = ID;
logger(LOG_ERR, "create_thread() failed: %s", strerror(errno));
abort();
}
logger(LOG_ERR, "create_thread() failed: %s", strerror(errno));
abort();
}
static inline void mutex_create(mutex_t *mutex) {
pthread_mutex_init(mutex, NULL);
}
static inline void mutex_create(mutex_t *mutex) {
pthread_mutex_init(mutex, NULL);
}
+#if 1
+#define mutex_lock(m) logger(LOG_DEBUG, "mutex_lock() at " __FILE__ " line %d", __LINE__); pthread_mutex_lock(m)
+#define mutex_unlock(m) logger(LOG_DEBUG, "mutex_unlock() at " __FILE__ " line %d", __LINE__); pthread_mutex_unlock(m)
+#else
static inline void mutex_lock(mutex_t *mutex) {
pthread_mutex_lock(mutex);
}
static inline void mutex_lock(mutex_t *mutex) {
pthread_mutex_lock(mutex);
}
pthread_mutex_unlock(mutex);
}
#endif
pthread_mutex_unlock(mutex);
}
#endif
#ifdef HAVE_MINGW
static struct WSAData wsa_state;
CRITICAL_SECTION mutex;
#ifdef HAVE_MINGW
static struct WSAData wsa_state;
CRITICAL_SECTION mutex;
+ mutex_create(&mutex);
+ mutex_lock(&mutex);
init_events();
init_configuration(&config_tree);
init_events();
init_configuration(&config_tree);