core: Use gcc atomics instead glib's ones
authorDaniel Wagner <daniel.wagner@bmw-carit.de>
Mon, 31 Oct 2011 12:19:09 +0000 (13:19 +0100)
committerSamuel Ortiz <sameo@linux.intel.com>
Thu, 10 Nov 2011 12:09:50 +0000 (13:09 +0100)
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
src/ipconfig.c
src/network.c
src/notifier.c
src/provider.c
src/service.c
src/task.c
src/technology.c
src/tethering.c

index 9ba7caf..29da1a1 100644 (file)
@@ -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) {
index da61446..b472990 100644 (file)
@@ -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);
 }
 
 /**
index cd0b9c8..090b7e7 100644 (file)
@@ -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);
index 332bafb..5ba2264 100644 (file)
@@ -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(&registered[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(&registered[type], 1) == 0)
+       if (__sync_fetch_and_add(&registered[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(&registered[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(&registered[type]) == TRUE)
-               technology_registered(type, FALSE);
+       if (__sync_fetch_and_sub(&registered[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(&registered[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;
index 7b5edae..27b0902 100644 (file)
@@ -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);
index 0026e16..30bf2fb 100644 (file)
@@ -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;
 }
index 2fd2567..41710cd 100644 (file)
@@ -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);
index c6fd826..4c816f6 100644 (file)
@@ -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;
 }
index c362b8d..b4ab993 100644 (file)
@@ -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);