From 23bc3ff71dffdfec208aee05938e544c7cb3bc37 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 30 Mar 2011 13:10:04 -0700 Subject: Don't futex_wait spin when setting properties. Wait for socket close. Depends on init change I8dd685ea Bug: 4185486 Change-Id: I5a2dbc3b7be1759212d4a3988d9033b9b947a1db --- libc/bionic/system_properties.c | 73 +++++++++++------------------------------ 1 file changed, 20 insertions(+), 53 deletions(-) (limited to 'libc/bionic') diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c index c40950f..3bdc9bf 100644 --- a/libc/bionic/system_properties.c +++ b/libc/bionic/system_properties.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -156,15 +157,17 @@ int __system_property_get(const char *name, char *value) static int send_prop_msg(prop_msg *msg) { + struct pollfd pollfds[1]; struct sockaddr_un addr; socklen_t alen; size_t namelen; int s; int r; + int result = -1; s = socket(AF_LOCAL, SOCK_STREAM, 0); if(s < 0) { - return -1; + return result; } memset(&addr, 0, sizeof(addr)); @@ -175,30 +178,37 @@ static int send_prop_msg(prop_msg *msg) if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen) < 0)) { close(s); - return -1; + return result; } r = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0)); if(r == sizeof(prop_msg)) { - r = 0; - } else { - r = -1; + // We successfully wrote to the property server but now we + // wait for the property server to finish its work. It + // acknowledges its completion by closing the socket so we + // poll here (on nothing), waiting for the socket to close. + // If you 'adb shell setprop foo bar' you'll see the POLLHUP + // once the socket closes. Out of paranoia we cap our poll + // at 250 ms. + pollfds[0].fd = s; + pollfds[0].events = 0; + r = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */)); + if (r == 1 && (pollfds[0].revents & POLLHUP) != 0) { + result = 0; + } } close(s); - return r; + return result; } int __system_property_set(const char *key, const char *value) { - unsigned old_serial; - volatile unsigned *serial; - prop_msg msg; int err; - prop_area *pa = __system_property_area__; int tries = 0; int update_seen = 0; + prop_msg msg; if(key == 0) return -1; if(value == 0) value = ""; @@ -210,54 +220,11 @@ int __system_property_set(const char *key, const char *value) strlcpy(msg.name, key, sizeof msg.name); strlcpy(msg.value, value, sizeof msg.value); - /* Note the system properties serial number before we do our update. */ - const prop_info *pi = __system_property_find(key); - if(pi != NULL) { - serial = &pi->serial; - } else { - serial = &pa->serial; - } - old_serial = *serial; - err = send_prop_msg(&msg); if(err < 0) { return err; } - /** - * Wait for the shared memory page to be written back and be - * visible in our address space before returning to the caller - * who might reasonably expect subsequent reads to match what was - * just written. - * - * Sleep 5 ms after failed checks and only wait up to a 500 ms - * total, just in case the system property server fails to update - * for whatever reason. - */ - do { - struct timespec timeout; - timeout.tv_sec = 0; - timeout.tv_nsec = 2500000; // 2.5 ms - - if(tries++ > 0) { - usleep(2500); // 2.5 ms - } - __futex_wait(serial, old_serial, &timeout); - if(pi != NULL) { - unsigned new_serial = *serial; - /* Waiting on a specific prop_info to be updated. */ - if (old_serial != new_serial && !SERIAL_DIRTY(new_serial)) { - update_seen = 1; - } - } else { - /* Waiting for a prop_info to be created. */ - const prop_info *new_pi = __system_property_find(key); - if(new_pi != NULL && !SERIAL_DIRTY(new_pi->serial)) { - update_seen = 1; - } - } - } while (!update_seen && tries < 100); - return 0; } -- cgit v1.1