From 9232d39e6a0738b750e97efd04124c81b7b2e583 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 31 Oct 2011 13:19:09 +0100 Subject: [PATCH] core: Use gcc atomics instead glib's ones g_atomic_int_exchange_and_add() has been removed from glib 2.30 and g_atomic_int_add() should be used. Though there are still quite a few distros out which do not ship a glib version with g_atomic_int_add(). Instead of maintaing a compatiblilty glib layer we just use the built-in functions for atomic memory access. --- src/device.c | 6 ++-- src/ipconfig.c | 33 +++++++++++----------- src/network.c | 10 +++---- src/notifier.c | 57 ++++++++++++++++++++++++-------------- src/provider.c | 6 ++-- src/service.c | 34 ++++++++++++----------- src/task.c | 7 +++-- src/technology.c | 21 +++++++------- src/tethering.c | 83 +++++++++++++++++++++++++++++--------------------------- 9 files changed, 139 insertions(+), 118 deletions(-) diff --git a/src/device.c b/src/device.c index 9ba7caf..29da1a1 100644 --- a/src/device.c +++ b/src/device.c @@ -39,7 +39,7 @@ enum connman_pending_type { }; struct connman_device { - gint refcount; + int refcount; enum connman_device_type type; enum connman_pending_type powered_pending; /* Indicates a pending enable/disable request */ @@ -536,7 +536,7 @@ struct connman_device *connman_device_ref(struct connman_device *device) { DBG("%p", device); - g_atomic_int_inc(&device->refcount); + __sync_fetch_and_add(&device->refcount, 1); return device; } @@ -549,7 +549,7 @@ struct connman_device *connman_device_ref(struct connman_device *device) */ void connman_device_unref(struct connman_device *device) { - if (g_atomic_int_dec_and_test(&device->refcount) == FALSE) + if (__sync_fetch_and_sub(&device->refcount, 1) != 1) return; if (device->driver) { diff --git a/src/ipconfig.c b/src/ipconfig.c index da61446..b472990 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -40,7 +40,7 @@ #include "connman.h" struct connman_ipconfig { - gint refcount; + int refcount; int index; enum connman_ipconfig_type type; @@ -1307,10 +1307,9 @@ struct connman_ipconfig *connman_ipconfig_create(int index, */ struct connman_ipconfig *connman_ipconfig_ref(struct connman_ipconfig *ipconfig) { - DBG("ipconfig %p refcount %d", ipconfig, - g_atomic_int_get(&ipconfig->refcount) + 1); + DBG("ipconfig %p refcount %d", ipconfig, ipconfig->refcount + 1); - g_atomic_int_inc(&ipconfig->refcount); + __sync_fetch_and_add(&ipconfig->refcount, 1); return ipconfig; } @@ -1326,24 +1325,24 @@ void connman_ipconfig_unref(struct connman_ipconfig *ipconfig) if (ipconfig == NULL) return; - DBG("ipconfig %p refcount %d", ipconfig, - g_atomic_int_get(&ipconfig->refcount) - 1); + DBG("ipconfig %p refcount %d", ipconfig, ipconfig->refcount - 1); - if (g_atomic_int_dec_and_test(&ipconfig->refcount) == TRUE) { - __connman_ipconfig_disable(ipconfig); + if (__sync_fetch_and_sub(&ipconfig->refcount, 1) != 1) + return; - connman_ipconfig_set_ops(ipconfig, NULL); + __connman_ipconfig_disable(ipconfig); - if (ipconfig->origin != NULL) { - connman_ipconfig_unref(ipconfig->origin); - ipconfig->origin = NULL; - } + connman_ipconfig_set_ops(ipconfig, NULL); - connman_ipaddress_free(ipconfig->system); - connman_ipaddress_free(ipconfig->address); - g_free(ipconfig->last_dhcp_address); - g_free(ipconfig); + if (ipconfig->origin != NULL) { + connman_ipconfig_unref(ipconfig->origin); + ipconfig->origin = NULL; } + + connman_ipaddress_free(ipconfig->system); + connman_ipaddress_free(ipconfig->address); + g_free(ipconfig->last_dhcp_address); + g_free(ipconfig); } /** diff --git a/src/network.c b/src/network.c index cd0b9c8..090b7e7 100644 --- a/src/network.c +++ b/src/network.c @@ -32,7 +32,7 @@ static GSList *network_list = NULL; static GSList *driver_list = NULL; struct connman_network { - gint refcount; + int refcount; enum connman_network_type type; connman_bool_t available; connman_bool_t connected; @@ -389,9 +389,9 @@ struct connman_network *connman_network_create(const char *identifier, struct connman_network *connman_network_ref(struct connman_network *network) { DBG("network %p name %s refcount %d", network, network->name, - g_atomic_int_get(&network->refcount) + 1); + network->refcount + 1); - g_atomic_int_inc(&network->refcount); + __sync_fetch_and_add(&network->refcount, 1); return network; } @@ -405,9 +405,9 @@ struct connman_network *connman_network_ref(struct connman_network *network) void connman_network_unref(struct connman_network *network) { DBG("network %p name %s refcount %d", network, network->name, - g_atomic_int_get(&network->refcount) - 1); + network->refcount - 1); - if (g_atomic_int_dec_and_test(&network->refcount) == FALSE) + if (__sync_fetch_and_sub(&network->refcount, 1) != 1) return; network_list = g_slist_remove(network_list, network); diff --git a/src/notifier.c b/src/notifier.c index 332bafb..5ba2264 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -73,21 +73,22 @@ void connman_notifier_unregister(struct connman_notifier *notifier) #define MAX_TECHNOLOGIES 10 -static volatile gint registered[MAX_TECHNOLOGIES]; -static volatile gint enabled[MAX_TECHNOLOGIES]; -static volatile gint connected[MAX_TECHNOLOGIES]; +static volatile int registered[MAX_TECHNOLOGIES]; +static volatile int enabled[MAX_TECHNOLOGIES]; +static volatile int connected[MAX_TECHNOLOGIES]; void __connman_notifier_list_registered(DBusMessageIter *iter, void *user_data) { int i; + __sync_synchronize(); for (i = 0; i < MAX_TECHNOLOGIES; i++) { const char *type = __connman_service_type2string(i); if (type == NULL) continue; - if (g_atomic_int_get(®istered[i]) > 0) + if (registered[i] > 0) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type); } @@ -97,13 +98,14 @@ void __connman_notifier_list_enabled(DBusMessageIter *iter, void *user_data) { int i; + __sync_synchronize(); for (i = 0; i < MAX_TECHNOLOGIES; i++) { const char *type = __connman_service_type2string(i); if (type == NULL) continue; - if (g_atomic_int_get(&enabled[i]) > 0) + if (enabled[i] > 0) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type); } @@ -113,13 +115,14 @@ void __connman_notifier_list_connected(DBusMessageIter *iter, void *user_data) { int i; + __sync_synchronize(); for (i = 0; i < MAX_TECHNOLOGIES; i++) { const char *type = __connman_service_type2string(i); if (type == NULL) continue; - if (g_atomic_int_get(&connected[i]) > 0) + if (connected[i] > 0) dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type); } @@ -158,8 +161,9 @@ unsigned int __connman_notifier_count_connected(void) { unsigned int i, count = 0; + __sync_synchronize(); for (i = 0; i < MAX_TECHNOLOGIES; i++) { - if (g_atomic_int_get(&connected[i]) > 0) + if (connected[i] > 0) count++; } @@ -238,7 +242,7 @@ void __connman_notifier_register(enum connman_service_type type) break; } - if (g_atomic_int_exchange_and_add(®istered[type], 1) == 0) + if (__sync_fetch_and_add(®istered[type], 1) == 0) technology_registered(type, TRUE); } @@ -246,7 +250,8 @@ void __connman_notifier_unregister(enum connman_service_type type) { DBG("type %d", type); - if (g_atomic_int_get(®istered[type]) == 0) { + __sync_synchronize(); + if (registered[type] == 0) { connman_error("notifier unregister underflow"); return; } @@ -266,8 +271,10 @@ void __connman_notifier_unregister(enum connman_service_type type) break; } - if (g_atomic_int_dec_and_test(®istered[type]) == TRUE) - technology_registered(type, FALSE); + if (__sync_fetch_and_sub(®istered[type], 1) != 1) + return; + + technology_registered(type, FALSE); } void __connman_notifier_enable(enum connman_service_type type) @@ -289,7 +296,7 @@ void __connman_notifier_enable(enum connman_service_type type) break; } - if (g_atomic_int_exchange_and_add(&enabled[type], 1) == 0) + if (__sync_fetch_and_add(&enabled[type], 1) == 0) technology_enabled(type, TRUE); } @@ -297,7 +304,8 @@ void __connman_notifier_disable(enum connman_service_type type) { DBG("type %d", type); - if (g_atomic_int_get(&enabled[type]) == 0) { + __sync_synchronize(); + if (enabled[type] == 0) { connman_error("notifier disable underflow"); return; } @@ -317,8 +325,10 @@ void __connman_notifier_disable(enum connman_service_type type) break; } - if (g_atomic_int_dec_and_test(&enabled[type]) == TRUE) - technology_enabled(type, FALSE); + if (__sync_fetch_and_sub(&enabled[type], 1) != 1) + return; + + technology_enabled(type, FALSE); } void __connman_notifier_connect(enum connman_service_type type) @@ -340,7 +350,7 @@ void __connman_notifier_connect(enum connman_service_type type) break; } - if (g_atomic_int_exchange_and_add(&connected[type], 1) == 0) + if (__sync_fetch_and_add(&connected[type], 1) == 0) technology_connected(type, TRUE); } @@ -348,7 +358,8 @@ void __connman_notifier_disconnect(enum connman_service_type type) { DBG("type %d", type); - if (g_atomic_int_get(&connected[type]) == 0) { + __sync_synchronize(); + if (connected[type] == 0) { connman_error("notifier disconnect underflow"); return; } @@ -368,8 +379,10 @@ void __connman_notifier_disconnect(enum connman_service_type type) break; } - if (g_atomic_int_dec_and_test(&connected[type]) == TRUE) - technology_connected(type, FALSE); + if (__sync_fetch_and_sub(&connected[type], 1) != 1) + return; + + technology_connected(type, FALSE); } static void technology_default(enum connman_service_type type) @@ -577,7 +590,8 @@ connman_bool_t __connman_notifier_is_registered(enum connman_service_type type) if (technology_supported(type) == FALSE) return FALSE; - if (g_atomic_int_get(®istered[type]) > 0) + __sync_synchronize(); + if (registered[type] > 0) return TRUE; return FALSE; @@ -590,7 +604,8 @@ connman_bool_t __connman_notifier_is_enabled(enum connman_service_type type) if (technology_supported(type) == FALSE) return FALSE; - if (g_atomic_int_get(&enabled[type]) > 0) + __sync_synchronize(); + if (enabled[type] > 0) return TRUE; return FALSE; diff --git a/src/provider.c b/src/provider.c index 7b5edae..27b0902 100644 --- a/src/provider.c +++ b/src/provider.c @@ -45,7 +45,7 @@ struct connman_route { }; struct connman_provider { - gint refcount; + int refcount; struct connman_service *vpn_service; int index; char *identifier; @@ -213,7 +213,7 @@ struct connman_provider *connman_provider_ref(struct connman_provider *provider) { DBG("provider %p refcount %d", provider, provider->refcount + 1); - g_atomic_int_inc(&provider->refcount); + __sync_fetch_and_add(&provider->refcount, 1); return provider; } @@ -235,7 +235,7 @@ void connman_provider_unref(struct connman_provider *provider) { DBG("provider %p refcount %d", provider, provider->refcount - 1); - if (g_atomic_int_dec_and_test(&provider->refcount) == FALSE) + if (__sync_fetch_and_sub(&provider->refcount, 1) != 1) return; provider_remove(provider); diff --git a/src/service.c b/src/service.c index 0026e16..30bf2fb 100644 --- a/src/service.c +++ b/src/service.c @@ -56,8 +56,8 @@ struct connman_stats_counter { }; struct connman_service { - gint refcount; - gint session_usage_count; + int refcount; + int session_usage_count; char *identifier; char *path; enum connman_service_type type; @@ -1985,17 +1985,17 @@ GSequence *__connman_service_get_list(struct connman_session *session, void __connman_service_session_inc(struct connman_service *service) { DBG("service %p ref count %d", service, - g_atomic_int_get(&service->session_usage_count) + 1); + service->session_usage_count + 1); - g_atomic_int_inc(&service->session_usage_count); + __sync_fetch_and_add(&service->session_usage_count, 1); } connman_bool_t __connman_service_session_dec(struct connman_service *service) { DBG("service %p ref count %d", service, - g_atomic_int_get(&service->session_usage_count) - 1); + service->session_usage_count - 1); - if (g_atomic_int_dec_and_test(&service->session_usage_count) == FALSE) + if (__sync_fetch_and_sub(&service->session_usage_count, 1) != 1) return FALSE; return TRUE; @@ -3456,20 +3456,22 @@ static void service_free(gpointer user_data) */ void __connman_service_put(struct connman_service *service) { + GSequenceIter *iter; + DBG("service %p", service); - if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) { - GSequenceIter *iter; + if (__sync_fetch_and_sub(&service->refcount, 1) != 1) + return; - iter = g_hash_table_lookup(service_hash, service->identifier); - if (iter != NULL) { - reply_pending(service, ECONNABORTED); + iter = g_hash_table_lookup(service_hash, service->identifier); + if (iter != NULL) { + reply_pending(service, ECONNABORTED); - __connman_service_disconnect(service); + __connman_service_disconnect(service); - g_sequence_remove(iter); - } else - service_free(service); + g_sequence_remove(iter); + } else { + service_free(service); } } @@ -3574,7 +3576,7 @@ struct connman_service *connman_service_ref(struct connman_service *service) { DBG("%p", service); - g_atomic_int_inc(&service->refcount); + __sync_fetch_and_add(&service->refcount, 1); return service; } diff --git a/src/task.c b/src/task.c index 2fd2567..41710cd 100644 --- a/src/task.c +++ b/src/task.c @@ -51,7 +51,7 @@ struct connman_task { static GHashTable *task_hash = NULL; -static volatile gint task_counter; +static volatile int task_counter; static DBusConnection *connection; @@ -105,7 +105,7 @@ struct connman_task *connman_task_create(const char *program) if (task == NULL) return NULL; - counter = g_atomic_int_exchange_and_add(&task_counter, 1); + counter = __sync_fetch_and_add(&task_counter, 1); task->path = g_strdup_printf("/task/%d", counter); task->pid = -1; @@ -425,7 +425,8 @@ int __connman_task_init(void) dbus_connection_add_filter(connection, task_filter, NULL, NULL); - g_atomic_int_set(&task_counter, 0); + task_counter = 0; + __sync_synchronize(); task_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free_task); diff --git a/src/technology.c b/src/technology.c index c6fd826..4c816f6 100644 --- a/src/technology.c +++ b/src/technology.c @@ -51,13 +51,13 @@ enum connman_technology_state { }; struct connman_technology { - gint refcount; + int refcount; enum connman_service_type type; enum connman_technology_state state; char *path; GHashTable *rfkill_list; GSList *device_list; - gint enabled; + int enabled; char *regdom; connman_bool_t tethering; @@ -575,7 +575,7 @@ static struct connman_technology *technology_get(enum connman_service_type type) technology = technology_find(type); if (technology != NULL) { - g_atomic_int_inc(&technology->refcount); + __sync_fetch_and_add(&technology->refcount, 1); goto done; } @@ -642,7 +642,7 @@ static void technology_put(struct connman_technology *technology) { DBG("technology %p", technology); - if (g_atomic_int_dec_and_test(&technology->refcount) == FALSE) + if (__sync_fetch_and_sub(&technology->refcount, 1) != 1) return; if (technology->driver) { @@ -809,7 +809,7 @@ int __connman_technology_enabled(enum connman_service_type type) if (technology == NULL) return -ENXIO; - if (g_atomic_int_exchange_and_add(&technology->enabled, 1) == 0) { + if (__sync_fetch_and_add(&technology->enabled, 1) == 0) { __connman_notifier_enable(type); technology->state = CONNMAN_TECHNOLOGY_STATE_ENABLED; state_changed(technology); @@ -914,11 +914,12 @@ int __connman_technology_disabled(enum connman_service_type type) technology->pending_timeout = 0; } - if (g_atomic_int_dec_and_test(&technology->enabled) == TRUE) { - __connman_notifier_disable(type); - technology->state = CONNMAN_TECHNOLOGY_STATE_OFFLINE; - state_changed(technology); - } + if (__sync_fetch_and_sub(&technology->enabled, 1) != 1) + return 0; + + __connman_notifier_disable(type); + technology->state = CONNMAN_TECHNOLOGY_STATE_OFFLINE; + state_changed(technology); return 0; } diff --git a/src/tethering.c b/src/tethering.c index c362b8d..b4ab993 100644 --- a/src/tethering.c +++ b/src/tethering.c @@ -65,7 +65,7 @@ #define PRIVATE_NETWORK_SECONDARY_DNS "8.8.4.4" static char *default_interface = NULL; -static volatile gint tethering_enabled; +static volatile int tethering_enabled; static GDHCPServer *tethering_dhcp_server = NULL; static DBusConnection *connection; static GHashTable *pn_hash; @@ -336,44 +336,44 @@ static void disable_nat(const char *interface) void __connman_tethering_set_enabled(void) { int err; + const char *dns; DBG("enabled %d", tethering_enabled + 1); - if (g_atomic_int_exchange_and_add(&tethering_enabled, 1) == 0) { - const char *dns; + if (__sync_fetch_and_add(&tethering_enabled, 1) != 0) + return; - err = create_bridge(BRIDGE_NAME); - if (err < 0) - return; + err = create_bridge(BRIDGE_NAME); + if (err < 0) + return; - err = enable_bridge(BRIDGE_NAME); - if (err < 0) { - remove_bridge(BRIDGE_NAME); - return; - } + err = enable_bridge(BRIDGE_NAME); + if (err < 0) { + remove_bridge(BRIDGE_NAME); + return; + } - dns = BRIDGE_IP; - if (__connman_dnsproxy_add_listener(BRIDGE_NAME) < 0) { - connman_error("Can't add listener %s to DNS proxy", + dns = BRIDGE_IP; + if (__connman_dnsproxy_add_listener(BRIDGE_NAME) < 0) { + connman_error("Can't add listener %s to DNS proxy", BRIDGE_NAME); - dns = BRIDGE_DNS; - } - - tethering_dhcp_server = - dhcp_server_start(BRIDGE_NAME, - BRIDGE_IP, BRIDGE_SUBNET, - BRIDGE_IP_START, BRIDGE_IP_END, - 24 * 3600, dns); - if (tethering_dhcp_server == NULL) { - disable_bridge(BRIDGE_NAME); - remove_bridge(BRIDGE_NAME); - return; - } - - enable_nat(default_interface); - - DBG("tethering started"); + dns = BRIDGE_DNS; + } + + tethering_dhcp_server = + dhcp_server_start(BRIDGE_NAME, + BRIDGE_IP, BRIDGE_SUBNET, + BRIDGE_IP_START, BRIDGE_IP_END, + 24 * 3600, dns); + if (tethering_dhcp_server == NULL) { + disable_bridge(BRIDGE_NAME); + remove_bridge(BRIDGE_NAME); + return; } + + enable_nat(default_interface); + + DBG("tethering started"); } void __connman_tethering_set_disabled(void) @@ -382,17 +382,18 @@ void __connman_tethering_set_disabled(void) __connman_dnsproxy_remove_listener(BRIDGE_NAME); - if (g_atomic_int_dec_and_test(&tethering_enabled) == TRUE) { - disable_nat(default_interface); + if (__sync_fetch_and_sub(&tethering_enabled, 1) != 1) + return; + + disable_nat(default_interface); - dhcp_server_stop(tethering_dhcp_server); + dhcp_server_stop(tethering_dhcp_server); - disable_bridge(BRIDGE_NAME); + disable_bridge(BRIDGE_NAME); - remove_bridge(BRIDGE_NAME); + remove_bridge(BRIDGE_NAME); - DBG("tethering stopped"); - } + DBG("tethering stopped"); } void __connman_tethering_update_interface(const char *interface) @@ -410,7 +411,8 @@ void __connman_tethering_update_interface(const char *interface) default_interface = g_strdup(interface); - if (!g_atomic_int_get(&tethering_enabled)) + __sync_synchronize(); + if (tethering_enabled == 0) return; enable_nat(interface); @@ -613,7 +615,8 @@ void __connman_tethering_cleanup(void) { DBG(""); - if (g_atomic_int_get(&tethering_enabled)) { + __sync_synchronize(); + if (tethering_enabled == 0) { if (tethering_dhcp_server) dhcp_server_stop(tethering_dhcp_server); disable_bridge(BRIDGE_NAME); -- 2.7.4