bus: make bus ref counting atomic
This is preparation to allow sd_bus_message obejcts to be processed in a different thread from their originating sd_bus object.
This commit is contained in:
parent
eb01ba5de1
commit
e4ee6e5cc3
|
@ -695,7 +695,8 @@ libsystemd_shared_la_SOURCES = \
|
||||||
src/shared/fileio.h \
|
src/shared/fileio.h \
|
||||||
src/shared/output-mode.h \
|
src/shared/output-mode.h \
|
||||||
src/shared/MurmurHash3.c \
|
src/shared/MurmurHash3.c \
|
||||||
src/shared/MurmurHash3.h
|
src/shared/MurmurHash3.h \
|
||||||
|
src/shared/refcnt.h
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
noinst_LTLIBRARIES += \
|
noinst_LTLIBRARIES += \
|
||||||
|
|
2
TODO
2
TODO
|
@ -42,8 +42,8 @@ Features:
|
||||||
- move to gvariant
|
- move to gvariant
|
||||||
- minimal locking around the memfd cache
|
- minimal locking around the memfd cache
|
||||||
- keep the connection fds around as long as the bus is open
|
- keep the connection fds around as long as the bus is open
|
||||||
- make ref counting atomic
|
|
||||||
- merge busctl into systemctl or so?
|
- merge busctl into systemctl or so?
|
||||||
|
- synthesize sd_bus_message objects from kernel messages
|
||||||
|
|
||||||
* in the final killing spree, detect processes from the root directory, and
|
* in the final killing spree, detect processes from the root directory, and
|
||||||
complain loudly if they have argv[0][0] == '@' set.
|
complain loudly if they have argv[0][0] == '@' set.
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "prioq.h"
|
#include "prioq.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "refcnt.h"
|
||||||
|
|
||||||
#include "sd-bus.h"
|
#include "sd-bus.h"
|
||||||
#include "bus-error.h"
|
#include "bus-error.h"
|
||||||
|
@ -77,7 +78,16 @@ enum bus_auth {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sd_bus {
|
struct sd_bus {
|
||||||
unsigned n_ref;
|
/* We use atomic ref counting here since sd_bus_message
|
||||||
|
objects retain references to their originating sd_bus but
|
||||||
|
we want to allow them to be processed in a different
|
||||||
|
thread. We won't provide full thread safety, but only the
|
||||||
|
bare minimum that makes it possible to use sd_bus and
|
||||||
|
sd_bus_message objects independently and on different
|
||||||
|
threads as long as each object is used only once at the
|
||||||
|
same time. */
|
||||||
|
RefCount n_ref;
|
||||||
|
|
||||||
enum bus_state state;
|
enum bus_state state;
|
||||||
int input_fd, output_fd;
|
int input_fd, output_fd;
|
||||||
int message_version;
|
int message_version;
|
||||||
|
|
|
@ -103,7 +103,7 @@ int sd_bus_new(sd_bus **ret) {
|
||||||
if (!r)
|
if (!r)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r->n_ref = 1;
|
r->n_ref = REFCNT_INIT;
|
||||||
r->input_fd = r->output_fd = -1;
|
r->input_fd = r->output_fd = -1;
|
||||||
r->message_version = 1;
|
r->message_version = 1;
|
||||||
r->negotiate_fds = true;
|
r->negotiate_fds = true;
|
||||||
|
@ -934,9 +934,8 @@ sd_bus *sd_bus_ref(sd_bus *bus) {
|
||||||
if (!bus)
|
if (!bus)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
assert(bus->n_ref > 0);
|
assert_se(REFCNT_INC(bus->n_ref) >= 2);
|
||||||
|
|
||||||
bus->n_ref++;
|
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,10 +943,7 @@ sd_bus *sd_bus_unref(sd_bus *bus) {
|
||||||
if (!bus)
|
if (!bus)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
assert(bus->n_ref > 0);
|
if (REFCNT_DEC(bus->n_ref) <= 0)
|
||||||
bus->n_ref--;
|
|
||||||
|
|
||||||
if (bus->n_ref <= 0)
|
|
||||||
bus_free(bus);
|
bus_free(bus);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2013 Lennart Poettering
|
||||||
|
|
||||||
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
/* A type-safe atomic refcounter */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile unsigned _value;
|
||||||
|
} RefCount;
|
||||||
|
|
||||||
|
#define REFCNT_GET(r) ((r)._value)
|
||||||
|
#define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1))
|
||||||
|
#define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1))
|
||||||
|
|
||||||
|
#define REFCNT_INIT ((RefCount) { ._value = 1 })
|
Loading…
Reference in New Issue