[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.19-603-g914876b

Colin Guthrie gitmailer-noreply at 0pointer.de
Tue Nov 16 13:45:11 PST 2010


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  f564c7d76371380980faa10ee3c756c3130c60bf (commit)

- Log -----------------------------------------------------------------
914876b core: New LIFO style flist implementation v2.2
b27be51 combine: Handle reappearing slave sinks in non-automatic mode.
13cce22 alsa: remove redundant call to snd_pcm_nonblock()
-----------------------------------------------------------------------

Summary of changes:
 src/modules/alsa/alsa-util.c |    2 -
 src/modules/module-combine.c |   26 +++++-
 src/pulsecore/flist.c        |  217 ++++++++++++-----------------------------
 3 files changed, 87 insertions(+), 158 deletions(-)

-----------------------------------------------------------------------

commit 13cce22268abf2b225c4f30e963dc731e662d540
Author: Pierre-Louis Bossart <pierre-louis.bossart at intel.com>
Date:   Thu Nov 11 10:19:25 2010 -0600

    alsa: remove redundant call to snd_pcm_nonblock()
    
    The PCM handle is already opened with the SND_PCM_NONBLOCK flag.
    This additional call is useless.
    
    Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at intel.com>

diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 2d0d356..7ea26e1 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -399,8 +399,6 @@ success:
 
     ret = 0;
 
-    snd_pcm_nonblock(pcm_handle, 1);
-
 finish:
 
     return ret;

commit b27be51f78d0134affd4eaadd2c437d181c080c5
Author: Antti-Ville Jansson <antti-ville.jansson at digia.com>
Date:   Fri Nov 12 09:52:48 2010 +0200

    combine: Handle reappearing slave sinks in non-automatic mode.
    
    Earlier, if slave sinks were unlinked in non-automatic mode, their
    re-appearance was disregarded. Now they are added back to the list of outputs.
    
    Signed-off-by: Antti-Ville Jansson <antti-ville.jansson at digia.com>
    Reviewed-by: Tanu Kaskinen <tanu.kaskinen at digia.com>

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 5f94fdd..01d7a4e 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -47,6 +47,7 @@
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/time-smoother.h>
+#include <pulsecore/strlist.h>
 
 #include "module-combine-symdef.h"
 
@@ -125,6 +126,8 @@ struct userdata {
     pa_bool_t automatic;
     pa_bool_t auto_desc;
 
+    pa_strlist *unlinked_slaves;
+
     pa_hook_slot *sink_put_slot, *sink_unlink_slot, *sink_state_changed_slot;
 
     pa_resample_method_t resample_method;
@@ -1026,11 +1029,23 @@ static pa_hook_result_t sink_put_hook_cb(pa_core *c, pa_sink *s, struct userdata
     pa_core_assert_ref(c);
     pa_sink_assert_ref(s);
     pa_assert(u);
-    pa_assert(u->automatic);
 
     if (!is_suitable_sink(u, s))
         return PA_HOOK_OK;
 
+    /* Check if the sink is a previously unlinked slave (non-automatic mode) */
+    if (!u->automatic) {
+        pa_strlist *l = u->unlinked_slaves;
+
+        while (l && !pa_streq(pa_strlist_data(l), s->name))
+            l = pa_strlist_next(l);
+
+        if (l)
+            u->unlinked_slaves = pa_strlist_remove(u->unlinked_slaves, s->name);
+        else
+            return PA_HOOK_OK;
+    }
+
     pa_log_info("Configuring new sink: %s", s->name);
     if (!(o = output_new(u, s))) {
         pa_log("Failed to create sink input on sink '%s'.", s->name);
@@ -1072,6 +1087,10 @@ static pa_hook_result_t sink_unlink_hook_cb(pa_core *c, pa_sink *s, struct userd
         return PA_HOOK_OK;
 
     pa_log_info("Unconfiguring sink: %s", s->name);
+
+    if (!u->automatic)
+        u->unlinked_slaves = pa_strlist_prepend(u->unlinked_slaves, s->name);
+
     output_free(o);
 
     return PA_HOOK_OK;
@@ -1297,10 +1316,9 @@ int pa__init(pa_module*m) {
                 goto fail;
             }
         }
-
-        u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_cb, u);
     }
 
+    u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_cb, u);
     u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_hook_cb, u);
     u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_state_changed_hook_cb, u);
 
@@ -1341,6 +1359,8 @@ void pa__done(pa_module*m) {
     if (!(u = m->userdata))
         return;
 
+    pa_strlist_free(u->unlinked_slaves);
+
     if (u->sink_put_slot)
         pa_hook_slot_free(u->sink_put_slot);
 

commit 914876b40a15be7316ed4610acd782c0abd2c332
Author: Jyri Sarha <jyri.sarha at nokia.com>
Date:   Mon Nov 30 16:55:27 2009 +0200

    core: New LIFO style flist implementation v2.2
    
    The old free list implementation used objects in FIFO style. This is
    bad because it tries keep all the objects ever used alive and in
    memory. This minimizes the changes that an allocated object is already
    in cache. When there is shortage of physical memory this may also
    increase change that newly allocated object is swapped out. LIFO
    (e.g. stack) style free list should help these issues. Like the old
    one the new implementation is also lock free. This version (v2.1) of
    the patch has a potential weakness fixed. The previous version (2.0)
    did segfault when popping from empty flist, this does not.

diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index 7e5ee24..8e8c3cd 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -2,6 +2,9 @@
   This file is part of PulseAudio.
 
   Copyright 2006-2008 Lennart Poettering
+  Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+  Contact: Jyri Sarha <Jyri.Sarha at nokia.com>
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as
@@ -34,198 +37,106 @@
 
 #include "flist.h"
 
-/* Algorithm is not perfect, in a few corner cases it will fail to pop
- * from the flist although it isn't empty, and fail to push into the
- * flist, although it isn't full.
- *
- * We keep a fixed size array of entries, each item is an atomic
- * pointer.
- *
- * To accelerate finding of used/unused cells we maintain a read and a
- * write index which is used like a ring buffer. After each push we
- * increase the write index and after each pop we increase the read
- * index.
- *
- * The indexes are incremented atomically and are never truncated to
- * the buffer size. Instead we assume that the buffer size is a power
- * of two and that the truncation can thus be done by applying a
- * simple AND on read.
- *
- * To make sure that we do not look for empty cells indefinitely we
- * maintain a length value which stores the number of used cells. From
- * this value the number of unused cells is easily calculated. Please
- * note that the length value is not updated atomically with the read
- * and write index and might thus be a few cells off the real
- * value. To deal with this we always look for N_EXTRA_SCAN extra
- * cells when pushing/popping entries.
- *
- * It might make sense to replace this implementation with a link list
- * stack or queue, which however requires DCAS to be simple. Patches
- * welcome.
- *
- * Please note that this algorithm is home grown.*/
-
 #define FLIST_SIZE 128
-#define N_EXTRA_SCAN 3
 
-/* For debugging purposes we can define _Y to put and extra thread
- * yield between each operation. */
+/* Lock free single linked list element. */
+struct pa_flist_elem {
+    pa_atomic_ptr_t next;
+    pa_atomic_ptr_t ptr;
+};
 
-#ifdef PROFILE
-#define _Y pa_thread_yield()
-#else
-#define _Y do { } while(0)
-#endif
+typedef struct pa_flist_elem pa_flist_elem;
 
 struct pa_flist {
     unsigned size;
-    pa_atomic_t length;
-    pa_atomic_t read_idx;
-    pa_atomic_t write_idx;
+    /* Stack that contains pointers stored into free list */
+    pa_atomic_ptr_t stored;
+    /* Stack that contains empty list elements */
+    pa_atomic_ptr_t empty;
+    pa_flist_elem table[0];
 };
 
-#define PA_FLIST_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_flist))))
+/* Lock free pop from linked list stack */
+static pa_flist_elem *stack_pop(pa_atomic_ptr_t *list) {
+    pa_flist_elem *poped;
+    pa_assert(list);
+
+    do {
+        poped = (pa_flist_elem *) pa_atomic_ptr_load(list);
+    } while (poped != NULL && !pa_atomic_ptr_cmpxchg(list, poped, pa_atomic_ptr_load(&poped->next)));
+
+    return poped;
+}
+
+/* Lock free push to linked list stack */
+static void stack_push(pa_atomic_ptr_t *list, pa_flist_elem *new_elem) {
+    pa_flist_elem *next;
+    pa_assert(list);
+
+    do {
+        next = pa_atomic_ptr_load(list);
+        pa_atomic_ptr_store(&new_elem->next, next);
+    } while (!pa_atomic_ptr_cmpxchg(list, next, new_elem));
+}
 
 pa_flist *pa_flist_new(unsigned size) {
     pa_flist *l;
+    unsigned i;
 
     if (!size)
         size = FLIST_SIZE;
 
-    pa_assert(pa_is_power_of_two(size));
-
-    l = pa_xmalloc0(PA_ALIGN(sizeof(pa_flist)) + (sizeof(pa_atomic_ptr_t) * size));
+    l = pa_xmalloc0(sizeof(pa_flist) + sizeof(pa_flist_elem) * size);
 
     l->size = size;
-
-    pa_atomic_store(&l->read_idx, 0);
-    pa_atomic_store(&l->write_idx, 0);
-    pa_atomic_store(&l->length, 0);
-
+    pa_atomic_ptr_store(&l->stored, NULL);
+    pa_atomic_ptr_store(&l->empty, NULL);
+    for (i=0; i < size; i++) {
+        stack_push(&l->empty, &l->table[i]);
+    }
     return l;
 }
 
-static unsigned reduce(pa_flist *l, unsigned value) {
-    return value & (l->size - 1);
-}
-
 void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) {
     pa_assert(l);
 
     if (free_cb) {
-        pa_atomic_ptr_t*cells;
-        unsigned idx;
-
-        cells = PA_FLIST_CELLS(l);
-
-        for (idx = 0; idx < l->size; idx ++) {
-            void *p;
-
-            if ((p = pa_atomic_ptr_load(&cells[idx])))
-                free_cb(p);
-        }
+        pa_flist_elem *elem;
+        while((elem = stack_pop(&l->stored)))
+            free_cb(pa_atomic_ptr_load(&elem->ptr));
     }
 
     pa_xfree(l);
 }
 
-int pa_flist_push(pa_flist*l, void *p) {
-    unsigned idx, n;
-    pa_atomic_ptr_t*cells;
-#ifdef PROFILE
-    unsigned len;
-#endif
-
+int pa_flist_push(pa_flist *l, void *p) {
+    pa_flist_elem *elem;
     pa_assert(l);
     pa_assert(p);
 
-    cells = PA_FLIST_CELLS(l);
-
-    n = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
-
-#ifdef PROFILE
-    len = n;
-#endif
-
-    _Y;
-    idx = reduce(l, (unsigned) pa_atomic_load(&l->write_idx));
-
-    for (; n > 0 ; n--) {
-
-        _Y;
-
-        if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
-
-            _Y;
-            pa_atomic_inc(&l->write_idx);
-
-            _Y;
-            pa_atomic_inc(&l->length);
-
-            return 0;
-        }
-
-        _Y;
-        idx = reduce(l, idx + 1);
+    elem = stack_pop(&l->empty);
+    if (elem == NULL) {
+        pa_log_warn("flist is full");
+        return -1;
     }
+    pa_atomic_ptr_store(&elem->ptr, p);
+    stack_push(&l->stored, elem);
 
-#ifdef PROFILE
-    if (len > N_EXTRA_SCAN)
-        pa_log_warn("Didn't  find free cell after %u iterations.", len);
-#endif
-
-    return -1;
+    return 0;
 }
 
-void* pa_flist_pop(pa_flist*l) {
-    unsigned idx, n;
-    pa_atomic_ptr_t *cells;
-#ifdef PROFILE
-    unsigned len;
-#endif
-
+void* pa_flist_pop(pa_flist *l) {
+    pa_flist_elem *elem;
+    void *ptr;
     pa_assert(l);
 
-    cells = PA_FLIST_CELLS(l);
-
-    n = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
+    elem = stack_pop(&l->stored);
+    if (elem == NULL)
+        return NULL;
 
-#ifdef PROFILE
-    len = n;
-#endif
-
-    _Y;
-    idx = reduce(l, (unsigned) pa_atomic_load(&l->read_idx));
-
-    for (; n > 0 ; n--) {
-        void *p;
-
-        _Y;
-        p = pa_atomic_ptr_load(&cells[idx]);
-
-        if (p) {
-
-            _Y;
-            if (!pa_atomic_ptr_cmpxchg(&cells[idx], p, NULL))
-                continue;
+    ptr = pa_atomic_ptr_load(&elem->ptr);
 
-            _Y;
-            pa_atomic_inc(&l->read_idx);
-
-            _Y;
-            pa_atomic_dec(&l->length);
-
-            return p;
-        }
-
-        _Y;
-        idx = reduce(l, idx+1);
-    }
-
-#ifdef PROFILE
-    if (len > N_EXTRA_SCAN)
-        pa_log_warn("Didn't find used cell after %u iterations.", len);
-#endif
+    stack_push(&l->empty, elem);
 
-    return NULL;
+    return ptr;
 }

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list