diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-03-10 18:03:02 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-03-10 18:03:02 +0000 |
commit | 23a7a287967089d70a7e30ca4c7421674691c503 (patch) | |
tree | 4e37acd3534109b74d55d31f330cbd3fa674e9aa | |
parent | 1976058109890892db8ec88bfd3273f79c459f6b (diff) | |
parent | ac57622985220de064059971f9ccb00905e9bd04 (diff) | |
download | qemu-23a7a287967089d70a7e30ca4c7421674691c503.zip qemu-23a7a287967089d70a7e30ca4c7421674691c503.tar.gz qemu-23a7a287967089d70a7e30ca4c7421674691c503.tar.bz2 |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
- scsi: improvements to error reporting and conversion to realize,
Coverity/sparse fix for iscsi driver
- RCU fallout: fix -daemonize and s390x system emulation
- KVM: kvm_stat improvements and new man page
- x86: SYSRET fix for VxWorks
# gpg: Signature made Tue Mar 10 10:18:45 2015 GMT using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream:
x86: fix SS selector in SYSRET
scsi: Convert remaining PCI HBAs to realize()
scsi: Improve error reporting for invalid drive property
hw: Propagate errors through qdev_prop_set_drive()
scsi: Clean up duplicated error in legacy if=scsi code
cpus: initialize cpu->memory_dispatch
rcu: handle forks safely
qemu-thread: do not use PTHREAD_MUTEX_ERRORCHECK
kvm_stat: add kvm_stat.1 man page
kvm_stat: add column headers to text UI
iscsi: Fix check for username
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | block/iscsi.c | 2 | ||||
-rw-r--r-- | exec.c | 1 | ||||
-rw-r--r-- | hw/arm/vexpress.c | 6 | ||||
-rw-r--r-- | hw/arm/virt.c | 6 | ||||
-rw-r--r-- | hw/block/pflash_cfi01.c | 4 | ||||
-rw-r--r-- | hw/block/pflash_cfi02.c | 4 | ||||
-rw-r--r-- | hw/core/qdev-properties-system.c | 22 | ||||
-rw-r--r-- | hw/scsi/esp-pci.c | 28 | ||||
-rw-r--r-- | hw/scsi/lsi53c895a.c | 13 | ||||
-rw-r--r-- | hw/scsi/megasas.c | 12 | ||||
-rw-r--r-- | hw/scsi/scsi-bus.c | 6 | ||||
-rw-r--r-- | hw/usb/dev-storage.c | 7 | ||||
-rw-r--r-- | include/hw/qdev-properties.h | 4 | ||||
-rwxr-xr-x | scripts/kvm/kvm_stat | 5 | ||||
-rw-r--r-- | scripts/kvm/kvm_stat.texi | 55 | ||||
-rw-r--r-- | target-i386/seg_helper.c | 4 | ||||
-rw-r--r-- | util/qemu-thread-posix.c | 6 | ||||
-rw-r--r-- | util/rcu.c | 33 |
19 files changed, 152 insertions, 75 deletions
@@ -84,6 +84,9 @@ HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF) ifdef BUILD_DOCS DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qmp-commands.txt +ifdef CONFIG_LINUX +DOCS+=kvm_stat.1 +endif ifdef CONFIG_VIRTFS DOCS+=fsdev/virtfs-proxy-helper.1 endif @@ -490,6 +493,12 @@ qemu-nbd.8: qemu-nbd.texi $(POD2MAN) --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \ " GEN $@") +kvm_stat.1: scripts/kvm/kvm_stat.texi + $(call quiet-command, \ + perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< kvm_stat.pod && \ + $(POD2MAN) --section=1 --center=" " --release=" " kvm_stat.pod > $@, \ + " GEN $@") + dvi: qemu-doc.dvi qemu-tech.dvi html: qemu-doc.html qemu-tech.html info: qemu-doc.info qemu-tech.info diff --git a/block/iscsi.c b/block/iscsi.c index 1fa855a..3e34b1f 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1326,7 +1326,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, goto out; } - if (iscsi_url->user != NULL) { + if (iscsi_url->user[0] != '\0') { ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd); if (ret != 0) { @@ -548,6 +548,7 @@ void cpu_exec_init(CPUArchState *env) #ifndef CONFIG_USER_ONLY cpu->as = &address_space_memory; cpu->thread_id = qemu_get_thread_id(); + cpu_reload_memory_map(cpu); #endif QTAILQ_INSERT_TAIL(&cpus, cpu, node); #if defined(CONFIG_USER_ONLY) diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 5933454..8496c16 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -515,9 +515,9 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name, { DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); - if (di && qdev_prop_set_drive(dev, "drive", - blk_by_legacy_dinfo(di))) { - abort(); + if (di) { + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di), + &error_abort); } qdev_prop_set_uint32(dev, "num-blocks", diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 69f51ac..93b7605 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -522,9 +522,9 @@ static void create_one_flash(const char *name, hwaddr flashbase, DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); const uint64_t sectorlength = 256 * 1024; - if (dinfo && qdev_prop_set_drive(dev, "drive", - blk_by_legacy_dinfo(dinfo))) { - abort(); + if (dinfo) { + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), + &error_abort); } qdev_prop_set_uint32(dev, "num-blocks", flashsize / sectorlength); diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 89d380e..d282695 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -969,8 +969,8 @@ pflash_t *pflash_cfi01_register(hwaddr base, { DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01); - if (blk && qdev_prop_set_drive(dev, "drive", blk)) { - abort(); + if (blk) { + qdev_prop_set_drive(dev, "drive", blk, &error_abort); } qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); qdev_prop_set_uint64(dev, "sector-length", sector_len); diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 389b4aa..074a005 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -773,8 +773,8 @@ pflash_t *pflash_cfi02_register(hwaddr base, { DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02); - if (blk && qdev_prop_set_drive(dev, "drive", blk)) { - abort(); + if (blk) { + qdev_prop_set_drive(dev, "drive", blk, &error_abort); } qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); qdev_prop_set_uint32(dev, "sector-length", sector_len); diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index a2e44bd..c413226 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -341,27 +341,25 @@ PropertyInfo qdev_prop_vlan = { .set = set_vlan, }; -int qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockBackend *value) +void qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value, Error **errp) { - Error *err = NULL; - object_property_set_str(OBJECT(dev), - value ? blk_name(value) : "", name, &err); - if (err) { - qerror_report_err(err); - error_free(err); - return -1; - } - return 0; + object_property_set_str(OBJECT(dev), value ? blk_name(value) : "", + name, errp); } void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockBackend *value) { - if (qdev_prop_set_drive(dev, name, value) < 0) { + Error *err = NULL; + + qdev_prop_set_drive(dev, name, value, &err); + if (err) { + error_report_err(err); exit(1); } } + void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) { diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index 00b7297..8d2242d 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -342,13 +342,12 @@ static const struct SCSIBusInfo esp_pci_scsi_info = { .cancel = esp_request_cancelled, }; -static int esp_pci_scsi_init(PCIDevice *dev) +static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp) { PCIESPState *pci = PCI_ESP(dev); DeviceState *d = DEVICE(dev); ESPState *s = &pci->esp; uint8_t *pci_conf; - Error *err = NULL; pci_conf = dev->config; @@ -367,13 +366,8 @@ static int esp_pci_scsi_init(PCIDevice *dev) scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL); if (!d->hotplugged) { - scsi_bus_legacy_handle_cmdline(&s->bus, &err); - if (err != NULL) { - error_free(err); - return -1; - } + scsi_bus_legacy_handle_cmdline(&s->bus, errp); } - return 0; } static void esp_pci_scsi_uninit(PCIDevice *d) @@ -388,7 +382,7 @@ static void esp_pci_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = esp_pci_scsi_init; + k->realize = esp_pci_scsi_realize; k->exit = esp_pci_scsi_uninit; k->vendor_id = PCI_VENDOR_ID_AMD; k->device_id = PCI_DEVICE_ID_AMD_SCSI; @@ -466,17 +460,19 @@ static void dc390_write_config(PCIDevice *dev, } } -static int dc390_scsi_init(PCIDevice *dev) +static void dc390_scsi_realize(PCIDevice *dev, Error **errp) { DC390State *pci = DC390(dev); + Error *err = NULL; uint8_t *contents; uint16_t chksum = 0; - int i, ret; + int i; /* init base class */ - ret = esp_pci_scsi_init(dev); - if (ret < 0) { - return ret; + esp_pci_scsi_realize(dev, &err); + if (err) { + error_propagate(errp, err); + return; } /* EEPROM */ @@ -503,8 +499,6 @@ static int dc390_scsi_init(PCIDevice *dev) chksum = 0x1234 - chksum; contents[EE_CHKSUM1] = chksum & 0xff; contents[EE_CHKSUM2] = chksum >> 8; - - return 0; } static void dc390_class_init(ObjectClass *klass, void *data) @@ -512,7 +506,7 @@ static void dc390_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = dc390_scsi_init; + k->realize = dc390_scsi_realize; k->config_read = dc390_read_config; k->config_write = dc390_write_config; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index db7d4b8..c5b0cc5 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -19,7 +19,6 @@ #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" #include "sysemu/dma.h" -#include "qemu/error-report.h" //#define DEBUG_LSI //#define DEBUG_LSI_REG @@ -2089,12 +2088,11 @@ static const struct SCSIBusInfo lsi_scsi_info = { .cancel = lsi_request_cancelled }; -static int lsi_scsi_init(PCIDevice *dev) +static void lsi_scsi_realize(PCIDevice *dev, Error **errp) { LSIState *s = LSI53C895A(dev); DeviceState *d = DEVICE(dev); uint8_t *pci_conf; - Error *err = NULL; pci_conf = dev->config; @@ -2117,13 +2115,8 @@ static int lsi_scsi_init(PCIDevice *dev) scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL); if (!d->hotplugged) { - scsi_bus_legacy_handle_cmdline(&s->bus, &err); - if (err != NULL) { - error_free(err); - return -1; - } + scsi_bus_legacy_handle_cmdline(&s->bus, errp); } - return 0; } static void lsi_class_init(ObjectClass *klass, void *data) @@ -2131,7 +2124,7 @@ static void lsi_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = lsi_scsi_init; + k->realize = lsi_scsi_realize; k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; k->device_id = PCI_DEVICE_ID_LSI_53C895A; k->class_id = PCI_CLASS_STORAGE_SCSI; diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 4852237..bf83b65 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2320,14 +2320,13 @@ static const struct SCSIBusInfo megasas_scsi_info = { .cancel = megasas_command_cancel, }; -static int megasas_scsi_init(PCIDevice *dev) +static void megasas_scsi_realize(PCIDevice *dev, Error **errp) { DeviceState *d = DEVICE(dev); MegasasState *s = MEGASAS(dev); MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s); uint8_t *pci_conf; int i, bar_type; - Error *err = NULL; pci_conf = dev->config; @@ -2407,13 +2406,8 @@ static int megasas_scsi_init(PCIDevice *dev) scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), &megasas_scsi_info, NULL); if (!d->hotplugged) { - scsi_bus_legacy_handle_cmdline(&s->bus, &err); - if (err != NULL) { - error_free(err); - return -1; - } + scsi_bus_legacy_handle_cmdline(&s->bus, errp); } - return 0; } static void @@ -2507,7 +2501,7 @@ static void megasas_class_init(ObjectClass *oc, void *data) MegasasBaseClass *e = MEGASAS_DEVICE_CLASS(oc); const MegasasInfo *info = data; - pc->init = megasas_scsi_init; + pc->realize = megasas_scsi_realize; pc->exit = megasas_scsi_uninit; pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; pc->device_id = info->device_id; diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index dca9576..bd2c0e4 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -242,8 +242,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, if (serial && object_property_find(OBJECT(dev), "serial", NULL)) { qdev_prop_set_string(dev, "serial", serial); } - if (qdev_prop_set_drive(dev, "drive", blk) < 0) { - error_setg(errp, "Setting drive property failed"); + qdev_prop_set_drive(dev, "drive", blk, &err); + if (err) { + error_propagate(errp, err); object_unparent(OBJECT(dev)); return NULL; } @@ -273,7 +274,6 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp) scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo), unit, false, -1, NULL, &err); if (err != NULL) { - error_report("%s", error_get_pretty(err)); error_propagate(errp, err); break; } diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 8edc314..dacefd7 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -664,6 +664,7 @@ static void usb_msd_realize_bot(USBDevice *dev, Error **errp) static USBDevice *usb_msd_init(USBBus *bus, const char *filename) { static int nr=0; + Error *err = NULL; char id[8]; QemuOpts *opts; DriveInfo *dinfo; @@ -707,8 +708,10 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) /* create guest device */ dev = usb_create(bus, "usb-storage"); - if (qdev_prop_set_drive(&dev->qdev, "drive", - blk_by_legacy_dinfo(dinfo)) < 0) { + qdev_prop_set_drive(&dev->qdev, "drive", blk_by_legacy_dinfo(dinfo), + &err); + if (err) { + error_report_err(err); object_unparent(OBJECT(dev)); return NULL; } diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 0772a56..d67dad5 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -168,8 +168,8 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value); void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value); -int qdev_prop_set_drive(DeviceState *dev, const char *name, - BlockBackend *value) QEMU_WARN_UNUSED_RESULT; +void qdev_prop_set_drive(DeviceState *dev, const char *name, + BlockBackend *value, Error **errp); void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockBackend *value); void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index c65cabd..7e5d256 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -519,7 +519,10 @@ def tui(screen, stats): def refresh(sleeptime): screen.erase() screen.addstr(0, 0, 'kvm statistics') - row = 2 + screen.addstr(2, 1, 'Event') + screen.addstr(2, 1 + label_width + number_width - len('Total'), 'Total') + screen.addstr(2, 1 + label_width + number_width + 8 - len('Current'), 'Current') + row = 3 s = stats.get() def sortkey(x): if s[x][1]: diff --git a/scripts/kvm/kvm_stat.texi b/scripts/kvm/kvm_stat.texi new file mode 100644 index 0000000..6ce00d8 --- /dev/null +++ b/scripts/kvm/kvm_stat.texi @@ -0,0 +1,55 @@ +@example +@c man begin SYNOPSIS +usage: kvm_stat [OPTION]... +@c man end +@end example + +@c man begin DESCRIPTION + +kvm_stat prints counts of KVM kernel module trace events. These events signify +state transitions such as guest mode entry and exit. + +This tool is useful for observing guest behavior from the host perspective. +Often conclusions about performance or buggy behavior can be drawn from the +output. + +The set of KVM kernel module trace events may be specific to the kernel version +or architecture. It is best to check the KVM kernel module source code for the +meaning of events. + +Note that trace events are counted globally across all running guests. + +@c man end + +@c man begin OPTIONS +@table @option +@item -1, --once, --batch + run in batch mode for one second +@item -l, --log + run in logging mode (like vmstat) +@item -t, --tracepoints + retrieve statistics from tracepoints +@item -d, --debugfs + retrieve statistics from debugfs +@item -f, --fields=@var{fields} + fields to display (regex) +@item -h, --help + show help message +@end table + +@c man end + +@ignore + +@setfilename kvm_stat +@settitle Report KVM kernel module event counters. + +@c man begin AUTHOR +Stefan Hajnoczi <stefanha@redhat.com> +@c man end + +@c man begin SEEALSO +perf(1), trace-cmd(1) +@c man end + +@end ignore diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index fa374d0..2bc757a 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -1043,7 +1043,7 @@ void helper_sysret(CPUX86State *env, int dflag) DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); env->eip = (uint32_t)env->regs[R_ECX]; } - cpu_x86_load_seg_cache(env, R_SS, selector + 8, + cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3, 0, 0xffffffff, DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | @@ -1056,7 +1056,7 @@ void helper_sysret(CPUX86State *env, int dflag) DESC_S_MASK | (3 << DESC_DPL_SHIFT) | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); env->eip = (uint32_t)env->regs[R_ECX]; - cpu_x86_load_seg_cache(env, R_SS, selector + 8, + cpu_x86_load_seg_cache(env, R_SS, (selector + 8) | 3, 0, 0xffffffff, DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index 50a29d8..ba67cec 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -51,12 +51,8 @@ static void error_exit(int err, const char *msg) void qemu_mutex_init(QemuMutex *mutex) { int err; - pthread_mutexattr_t mutexattr; - pthread_mutexattr_init(&mutexattr); - pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK); - err = pthread_mutex_init(&mutex->lock, &mutexattr); - pthread_mutexattr_destroy(&mutexattr); + err = pthread_mutex_init(&mutex->lock, NULL); if (err) error_exit(err, __func__); } @@ -283,7 +283,7 @@ void rcu_unregister_thread(void) qemu_mutex_unlock(&rcu_gp_lock); } -static void __attribute__((__constructor__)) rcu_init(void) +static void rcu_init_complete(void) { QemuThread thread; @@ -291,8 +291,39 @@ static void __attribute__((__constructor__)) rcu_init(void) qemu_event_init(&rcu_gp_event, true); qemu_event_init(&rcu_call_ready_event, false); + + /* The caller is assumed to have iothread lock, so the call_rcu thread + * must have been quiescent even after forking, just recreate it. + */ qemu_thread_create(&thread, "call_rcu", call_rcu_thread, NULL, QEMU_THREAD_DETACHED); rcu_register_thread(); } + +#ifdef CONFIG_POSIX +static void rcu_init_lock(void) +{ + qemu_mutex_lock(&rcu_gp_lock); +} + +static void rcu_init_unlock(void) +{ + qemu_mutex_unlock(&rcu_gp_lock); +} + +static void rcu_init_child(void) +{ + qemu_mutex_unlock(&rcu_gp_lock); + memset(®istry, 0, sizeof(registry)); + rcu_init_complete(); +} +#endif + +static void __attribute__((__constructor__)) rcu_init(void) +{ +#ifdef CONFIG_POSIX + pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_child); +#endif + rcu_init_complete(); +} |