/** * Allocates the given number of bytes, as with standard malloc(), but * all bytes are initialized to zero as with calloc(). Guaranteed to * return #NULL if bytes is zero on all platforms. Returns #NULL if the * allocation fails. The memory must be released with dbus_free(). * * dbus_malloc0() memory is NOT safe to free with regular free() from * the C library. Free it with dbus_free() only. * * @param bytes number of bytes to allocate * @return allocated memory, or #NULL if the allocation fails. */ void* dbus_malloc0 (size_t bytes) { #ifdef DBUS_BUILD_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes); return NULL; } #endif if (bytes == 0) return NULL; #ifdef DBUS_BUILD_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) { void *block; block = calloc (bytes + GUARD_EXTRA_SIZE, 1); if (block) { _dbus_atomic_inc (&n_blocks_outstanding); } else if (malloc_cannot_fail) { _dbus_warn ("out of memory: calloc (%ld + %ld, 1)\n", (long) bytes, (long) GUARD_EXTRA_SIZE); _dbus_abort (); } return set_guards (block, bytes, SOURCE_MALLOC_ZERO); } #endif else { void *mem; mem = calloc (bytes, 1); #ifdef DBUS_BUILD_TESTS if (mem) { _dbus_atomic_inc (&n_blocks_outstanding); } else if (malloc_cannot_fail) { _dbus_warn ("out of memory: calloc (%ld)\n", (long) bytes); _dbus_abort (); } #endif return mem; } }
/** * Allocates the given number of bytes, as with standard * malloc(). Guaranteed to return #NULL if bytes is zero * on all platforms. Returns #NULL if the allocation fails. * The memory must be released with dbus_free(). * * dbus_malloc() memory is NOT safe to free with regular free() from * the C library. Free it with dbus_free() only. * * @param bytes number of bytes to allocate * @return allocated memory, or #NULL if the allocation fails. */ void* dbus_malloc (size_t bytes) { #ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes); return NULL; } #endif if (bytes == 0) /* some system mallocs handle this, some don't */ return NULL; #ifdef DBUS_ENABLE_EMBEDDED_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) { void *block; block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) { _dbus_atomic_inc (&n_blocks_outstanding); } else if (malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld + %ld)\n", (long) bytes, (long) GUARD_EXTRA_SIZE); _dbus_abort (); } return set_guards (block, bytes, SOURCE_MALLOC); } #endif else { void *mem; mem = malloc (bytes); #ifdef DBUS_ENABLE_EMBEDDED_TESTS if (mem) { _dbus_atomic_inc (&n_blocks_outstanding); } else if (malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); _dbus_abort (); } #endif return mem; } }
/** * Increments the reference count on a pending call, * while the lock on its connection is already held. * * @param pending the pending call object * @returns the pending call object */ DBusPendingCall * _dbus_pending_call_ref_unlocked (DBusPendingCall *pending) { _dbus_atomic_inc (&pending->refcount); return pending; }
/** * Increments the reference count on a pending call. * * @param pending the pending call object * @returns the pending call object */ DBusPendingCall * dbus_pending_call_ref (DBusPendingCall *pending) { _dbus_return_val_if_fail (pending != NULL, NULL); _dbus_atomic_inc (&pending->refcount); return pending; }
/** * Increments the reference count on a pending call, * while the lock on its connection is already held. * * @param pending the pending call object * @returns the pending call object */ DBusPendingCall * _dbus_pending_call_ref_unlocked (DBusPendingCall *pending) { dbus_int32_t old_refcount; old_refcount = _dbus_atomic_inc (&pending->refcount); _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1, "ref_unlocked"); return pending; }
/** * Creates a new pending reply object. * * @param connection connection where reply will arrive * @param timeout_milliseconds length of timeout, -1 (or * #DBUS_TIMEOUT_USE_DEFAULT) for default, * #DBUS_TIMEOUT_INFINITE for no timeout * @param timeout_handler timeout handler, takes pending call as data * @returns a new #DBusPendingCall or #NULL if no memory. */ DBusPendingCall* _dbus_pending_call_new_unlocked (DBusConnection *connection, int timeout_milliseconds, DBusTimeoutHandler timeout_handler) { DBusPendingCall *pending; DBusTimeout *timeout; _dbus_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1); if (timeout_milliseconds == -1) timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; if (!dbus_pending_call_allocate_data_slot (¬ify_user_data_slot)) return NULL; pending = dbus_new0 (DBusPendingCall, 1); if (pending == NULL) { dbus_pending_call_free_data_slot (¬ify_user_data_slot); return NULL; } if (timeout_milliseconds != DBUS_TIMEOUT_INFINITE) { timeout = _dbus_timeout_new (timeout_milliseconds, timeout_handler, pending, NULL); if (timeout == NULL) { dbus_pending_call_free_data_slot (¬ify_user_data_slot); dbus_free (pending); return NULL; } pending->timeout = timeout; } else { pending->timeout = NULL; } _dbus_atomic_inc (&pending->refcount); pending->connection = connection; _dbus_connection_ref_unlocked (pending->connection); _dbus_data_slot_list_init (&pending->slot_list); _dbus_pending_call_trace_ref (pending, 0, 1, "new_unlocked"); return pending; }
/** * Like dbus_server_ref() but does not acquire the lock (must already be held) * * @param server the server. */ void _dbus_server_ref_unlocked (DBusServer *server) { dbus_int32_t old_refcount; _dbus_assert (server != NULL); HAVE_LOCK_CHECK (server); old_refcount = _dbus_atomic_inc (&server->refcount); _dbus_assert (old_refcount > 0); _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref_unlocked"); }
/** * Increments the reference count on a pending call. * * @param pending the pending call object * @returns the pending call object */ DBusPendingCall * dbus_pending_call_ref (DBusPendingCall *pending) { dbus_int32_t old_refcount; _dbus_return_val_if_fail (pending != NULL, NULL); old_refcount = _dbus_atomic_inc (&pending->refcount); _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1, "ref"); return pending; }
/** * Like dbus_server_ref() but does not acquire the lock (must already be held) * * @param server the server. */ void _dbus_server_ref_unlocked (DBusServer *server) { _dbus_assert (server != NULL); _dbus_assert (server->refcount.value > 0); HAVE_LOCK_CHECK (server); #ifdef DBUS_HAVE_ATOMIC_INT _dbus_atomic_inc (&server->refcount); #else _dbus_assert (server->refcount.value > 0); server->refcount.value += 1; #endif }
/** * Increments the reference count of a DBusServer. * * @param server the server. * @returns the server */ DBusServer * dbus_server_ref (DBusServer *server) { _dbus_return_val_if_fail (server != NULL, NULL); _dbus_return_val_if_fail (server->refcount.value > 0, NULL); #ifdef DBUS_HAVE_ATOMIC_INT _dbus_atomic_inc (&server->refcount); #else SERVER_LOCK (server); _dbus_assert (server->refcount.value > 0); server->refcount.value += 1; SERVER_UNLOCK (server); #endif return server; }
/** * Decrements the reference count of a DBusServer. Finalizes the * server if the reference count reaches zero. * * The server must be disconnected before the refcount reaches zero. * * @param server the server. */ void dbus_server_unref (DBusServer *server) { dbus_int32_t old_refcount; /* keep this in sync with unref_unlocked */ _dbus_return_if_fail (server != NULL); old_refcount = _dbus_atomic_dec (&server->refcount); #ifndef DBUS_DISABLE_CHECKS if (_DBUS_UNLIKELY (old_refcount <= 0)) { /* undo side-effect first * please do not try to simplify the code here by using * _dbus_atomic_get(), why we don't use it is * because it issues another atomic operation even though * DBUS_DISABLE_CHECKS defined. * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68303 */ _dbus_atomic_inc (&server->refcount); _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, _DBUS_FUNCTION_NAME, "old_refcount > 0", __FILE__, __LINE__); return; } #endif _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref"); if (old_refcount == 1) { /* lock not held! */ _dbus_assert (server->disconnected); _dbus_assert (server->vtable->finalize != NULL); (* server->vtable->finalize) (server); } }
EXPORT_C #endif DBusPendingCall * dbus_pending_call_ref (DBusPendingCall *pending) { _dbus_return_val_if_fail (pending != NULL, NULL); /* The connection lock is better than the global * lock in the atomic increment fallback */ #ifdef DBUS_HAVE_ATOMIC_INT _dbus_atomic_inc (&pending->refcount); #else CONNECTION_LOCK (pending->connection); _dbus_assert (pending->refcount.value > 0); pending->refcount.value += 1; CONNECTION_UNLOCK (pending->connection); #endif return pending; }
/** * Increments the reference count of a DBusServer. * * @param server the server. * @returns the server */ DBusServer * dbus_server_ref (DBusServer *server) { dbus_int32_t old_refcount; _dbus_return_val_if_fail (server != NULL, NULL); old_refcount = _dbus_atomic_inc (&server->refcount); #ifndef DBUS_DISABLE_CHECKS if (_DBUS_UNLIKELY (old_refcount <= 0)) { _dbus_atomic_dec (&server->refcount); _dbus_warn_return_if_fail (_DBUS_FUNCTION_NAME, "old_refcount > 0", __FILE__, __LINE__); return NULL; } #endif _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref"); return server; }
/** * Resizes a block of memory previously allocated by dbus_malloc() or * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes * is zero on all platforms. Returns #NULL if the resize fails. * If the resize fails, the memory is not freed. * * @param memory block to be resized * @param bytes new size of the memory block * @return allocated memory, or #NULL if the resize fails. */ void* dbus_realloc (void *memory, size_t bytes) { #ifdef DBUS_BUILD_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes); return NULL; } #endif if (bytes == 0) /* guarantee this is safe */ { dbus_free (memory); return NULL; } #ifdef DBUS_BUILD_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) { if (memory) { size_t old_bytes; void *block; check_guards (memory, FALSE); block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE); old_bytes = *(dbus_uint32_t*)block; if (block && bytes >= old_bytes) /* old guards shouldn't have moved */ check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE); return set_guards (block, bytes, SOURCE_REALLOC); } else { void *block; block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) _dbus_atomic_inc (&n_blocks_outstanding); return set_guards (block, bytes, SOURCE_REALLOC_NULL); } } #endif else { void *mem; mem = realloc (memory, bytes); #ifdef DBUS_BUILD_TESTS if (memory == NULL && mem != NULL) _dbus_atomic_inc (&n_blocks_outstanding); #endif return mem; } }
/** * Initializes the members of the DBusServer base class. * Chained up to by subclass constructors. * * @param server the server. * @param vtable the vtable for the subclass. * @param address the server's address * @returns #TRUE on success. */ dbus_bool_t _dbus_server_init_base (DBusServer *server, const DBusServerVTable *vtable, const DBusString *address) { server->vtable = vtable; #ifdef DBUS_DISABLE_ASSERT _dbus_atomic_inc (&server->refcount); #else { dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); _dbus_assert (old_refcount == 0); } #endif server->address = NULL; server->watches = NULL; server->timeouts = NULL; server->published_address = FALSE; if (!_dbus_string_init (&server->guid_hex)) return FALSE; _dbus_generate_uuid (&server->guid); if (!_dbus_uuid_encode (&server->guid, &server->guid_hex)) goto failed; server->address = copy_address_with_guid_appended (address, &server->guid_hex); if (server->address == NULL) goto failed; _dbus_rmutex_new_at_location (&server->mutex); if (server->mutex == NULL) goto failed; server->watches = _dbus_watch_list_new (); if (server->watches == NULL) goto failed; server->timeouts = _dbus_timeout_list_new (); if (server->timeouts == NULL) goto failed; _dbus_data_slot_list_init (&server->slot_list); _dbus_verbose ("Initialized server on address %s\n", server->address); return TRUE; failed: _dbus_rmutex_free_at_location (&server->mutex); server->mutex = NULL; if (server->watches) { _dbus_watch_list_free (server->watches); server->watches = NULL; } if (server->timeouts) { _dbus_timeout_list_free (server->timeouts); server->timeouts = NULL; } if (server->address) { dbus_free (server->address); server->address = NULL; } _dbus_string_free (&server->guid_hex); return FALSE; }
/** * Resizes a block of memory previously allocated by dbus_malloc() or * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes * is zero on all platforms. Returns #NULL if the resize fails. * If the resize fails, the memory is not freed. * * @param memory block to be resized * @param bytes new size of the memory block * @return allocated memory, or #NULL if the resize fails. */ void* _dbus_realloc (void *memory, size_t bytes, const char *file, int line) { #ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes); return NULL; } #endif if (bytes == 0) /* guarantee this is safe */ { dbus_free (memory); return NULL; } #ifdef DBUS_ENABLE_EMBEDDED_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) { if (memory) { size_t old_bytes; void *block; check_guards (memory, FALSE); block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE); if (block == NULL) { if (malloc_cannot_fail) { _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n", memory, (long) bytes, (long) GUARD_EXTRA_SIZE); _dbus_abort (); } return NULL; } dbus_track_free (((unsigned char*)memory) - GUARD_START_OFFSET); dbus_track_realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE, file, line); old_bytes = *(dbus_uint32_t*)block; if (bytes >= old_bytes) /* old guards shouldn't have moved */ check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE); return set_guards (block, bytes, SOURCE_REALLOC); } else { void *block; block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) { _dbus_atomic_inc (&n_blocks_outstanding); dbus_track_malloc(block, bytes + GUARD_EXTRA_SIZE, file, line); } else if (malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld + %ld)\n", (long) bytes, (long) GUARD_EXTRA_SIZE); _dbus_abort (); } return set_guards (block, bytes, SOURCE_REALLOC_NULL); } } #endif else { void *mem; mem = realloc (memory, bytes); #ifdef DBUS_ENABLE_EMBEDDED_TESTS if (mem == NULL && malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); _dbus_abort (); } if (memory == NULL && mem != NULL) _dbus_atomic_inc (&n_blocks_outstanding); #endif dbus_track_free (memory); dbus_track_realloc (mem, bytes, file, line); return mem; } }