153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci  This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci  PulseAudio is free software; you can redistribute it and/or modify
553a5a1b3Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as published
653a5a1b3Sopenharmony_ci  by the Free Software Foundation; either version 2.1 of the License,
753a5a1b3Sopenharmony_ci  or (at your option) any later version.
853a5a1b3Sopenharmony_ci
953a5a1b3Sopenharmony_ci  PulseAudio is distributed in the hope that it will be useful, but
1053a5a1b3Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1153a5a1b3Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1253a5a1b3Sopenharmony_ci  General Public License for more details.
1353a5a1b3Sopenharmony_ci
1453a5a1b3Sopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1553a5a1b3Sopenharmony_ci  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1653a5a1b3Sopenharmony_ci***/
1753a5a1b3Sopenharmony_ci
1853a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
1953a5a1b3Sopenharmony_ci#include <config.h>
2053a5a1b3Sopenharmony_ci#endif
2153a5a1b3Sopenharmony_ci
2253a5a1b3Sopenharmony_ci#include <stdio.h>
2353a5a1b3Sopenharmony_ci#include <unistd.h>
2453a5a1b3Sopenharmony_ci
2553a5a1b3Sopenharmony_ci#include <check.h>
2653a5a1b3Sopenharmony_ci
2753a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h>
2853a5a1b3Sopenharmony_ci
2953a5a1b3Sopenharmony_ci#include <pulsecore/log.h>
3053a5a1b3Sopenharmony_ci#include <pulsecore/memblock.h>
3153a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
3253a5a1b3Sopenharmony_ci
3353a5a1b3Sopenharmony_cistatic void release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
3453a5a1b3Sopenharmony_ci    pa_log("%s: Imported block %u is released.", (char*) userdata, block_id);
3553a5a1b3Sopenharmony_ci}
3653a5a1b3Sopenharmony_ci
3753a5a1b3Sopenharmony_cistatic void revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) {
3853a5a1b3Sopenharmony_ci    pa_log("%s: Exported block %u is revoked.", (char*) userdata, block_id);
3953a5a1b3Sopenharmony_ci}
4053a5a1b3Sopenharmony_ci
4153a5a1b3Sopenharmony_cistatic void print_stats(pa_mempool *p, const char *text) {
4253a5a1b3Sopenharmony_ci    const pa_mempool_stat*s = pa_mempool_get_stat(p);
4353a5a1b3Sopenharmony_ci
4453a5a1b3Sopenharmony_ci    pa_log_debug("%s = {\n"
4553a5a1b3Sopenharmony_ci                 "\tn_allocated = %u\n"
4653a5a1b3Sopenharmony_ci                 "\tn_accumulated = %u\n"
4753a5a1b3Sopenharmony_ci                 "\tn_imported = %u\n"
4853a5a1b3Sopenharmony_ci                 "\tn_exported = %u\n"
4953a5a1b3Sopenharmony_ci                 "\tallocated_size = %u\n"
5053a5a1b3Sopenharmony_ci                 "\taccumulated_size = %u\n"
5153a5a1b3Sopenharmony_ci                 "\timported_size = %u\n"
5253a5a1b3Sopenharmony_ci                 "\texported_size = %u\n"
5353a5a1b3Sopenharmony_ci                 "\tn_too_large_for_pool = %u\n"
5453a5a1b3Sopenharmony_ci                 "\tn_pool_full = %u\n"
5553a5a1b3Sopenharmony_ci                 "}",
5653a5a1b3Sopenharmony_ci           text,
5753a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->n_allocated),
5853a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->n_accumulated),
5953a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->n_imported),
6053a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->n_exported),
6153a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->allocated_size),
6253a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->accumulated_size),
6353a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->imported_size),
6453a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->exported_size),
6553a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->n_too_large_for_pool),
6653a5a1b3Sopenharmony_ci           (unsigned) pa_atomic_load(&s->n_pool_full));
6753a5a1b3Sopenharmony_ci}
6853a5a1b3Sopenharmony_ci
6953a5a1b3Sopenharmony_ciSTART_TEST (memblock_test) {
7053a5a1b3Sopenharmony_ci    pa_mempool *pool_a, *pool_b, *pool_c;
7153a5a1b3Sopenharmony_ci    unsigned id_a, id_b, id_c;
7253a5a1b3Sopenharmony_ci    pa_memexport *export_a, *export_b;
7353a5a1b3Sopenharmony_ci    pa_memimport *import_b, *import_c;
7453a5a1b3Sopenharmony_ci    pa_memblock *mb_a, *mb_b, *mb_c;
7553a5a1b3Sopenharmony_ci    int r, i;
7653a5a1b3Sopenharmony_ci    pa_memblock* blocks[5];
7753a5a1b3Sopenharmony_ci    pa_mem_type_t mem_type;
7853a5a1b3Sopenharmony_ci    uint32_t id, shm_id;
7953a5a1b3Sopenharmony_ci    size_t offset, size;
8053a5a1b3Sopenharmony_ci    char *x;
8153a5a1b3Sopenharmony_ci
8253a5a1b3Sopenharmony_ci    const char txt[] = "This is a test!";
8353a5a1b3Sopenharmony_ci
8453a5a1b3Sopenharmony_ci    pool_a = pa_mempool_new(PA_MEM_TYPE_SHARED_POSIX, 0, true);
8553a5a1b3Sopenharmony_ci    fail_unless(pool_a != NULL);
8653a5a1b3Sopenharmony_ci    pool_b = pa_mempool_new(PA_MEM_TYPE_SHARED_POSIX, 0, true);
8753a5a1b3Sopenharmony_ci    fail_unless(pool_b != NULL);
8853a5a1b3Sopenharmony_ci    pool_c = pa_mempool_new(PA_MEM_TYPE_SHARED_POSIX, 0, true);
8953a5a1b3Sopenharmony_ci    fail_unless(pool_c != NULL);
9053a5a1b3Sopenharmony_ci
9153a5a1b3Sopenharmony_ci    pa_mempool_get_shm_id(pool_a, &id_a);
9253a5a1b3Sopenharmony_ci    pa_mempool_get_shm_id(pool_b, &id_b);
9353a5a1b3Sopenharmony_ci    pa_mempool_get_shm_id(pool_c, &id_c);
9453a5a1b3Sopenharmony_ci
9553a5a1b3Sopenharmony_ci    blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1);
9653a5a1b3Sopenharmony_ci
9753a5a1b3Sopenharmony_ci    blocks[1] = pa_memblock_new(pool_a, sizeof(txt));
9853a5a1b3Sopenharmony_ci    x = pa_memblock_acquire(blocks[1]);
9953a5a1b3Sopenharmony_ci    snprintf(x, pa_memblock_get_length(blocks[1]), "%s", txt);
10053a5a1b3Sopenharmony_ci    pa_memblock_release(blocks[1]);
10153a5a1b3Sopenharmony_ci
10253a5a1b3Sopenharmony_ci    blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt));
10353a5a1b3Sopenharmony_ci    x = pa_memblock_acquire(blocks[2]);
10453a5a1b3Sopenharmony_ci    snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt);
10553a5a1b3Sopenharmony_ci    pa_memblock_release(blocks[2]);
10653a5a1b3Sopenharmony_ci
10753a5a1b3Sopenharmony_ci    blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt));
10853a5a1b3Sopenharmony_ci    blocks[4] = NULL;
10953a5a1b3Sopenharmony_ci
11053a5a1b3Sopenharmony_ci    for (i = 0; blocks[i]; i++) {
11153a5a1b3Sopenharmony_ci        pa_log("Memory block %u", i);
11253a5a1b3Sopenharmony_ci
11353a5a1b3Sopenharmony_ci        mb_a = blocks[i];
11453a5a1b3Sopenharmony_ci        fail_unless(mb_a != NULL);
11553a5a1b3Sopenharmony_ci
11653a5a1b3Sopenharmony_ci        export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A");
11753a5a1b3Sopenharmony_ci        fail_unless(export_a != NULL);
11853a5a1b3Sopenharmony_ci        export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B");
11953a5a1b3Sopenharmony_ci        fail_unless(export_b != NULL);
12053a5a1b3Sopenharmony_ci
12153a5a1b3Sopenharmony_ci        import_b = pa_memimport_new(pool_b, release_cb, (void*) "B");
12253a5a1b3Sopenharmony_ci        fail_unless(import_b != NULL);
12353a5a1b3Sopenharmony_ci        import_c = pa_memimport_new(pool_c, release_cb, (void*) "C");
12453a5a1b3Sopenharmony_ci        fail_unless(import_b != NULL);
12553a5a1b3Sopenharmony_ci
12653a5a1b3Sopenharmony_ci        r = pa_memexport_put(export_a, mb_a, &mem_type, &id, &shm_id, &offset, &size);
12753a5a1b3Sopenharmony_ci        fail_unless(r >= 0);
12853a5a1b3Sopenharmony_ci        fail_unless(shm_id == id_a);
12953a5a1b3Sopenharmony_ci
13053a5a1b3Sopenharmony_ci        pa_log("A: Memory block exported as %u", id);
13153a5a1b3Sopenharmony_ci
13253a5a1b3Sopenharmony_ci        mb_b = pa_memimport_get(import_b, PA_MEM_TYPE_SHARED_POSIX, id, shm_id, offset, size, false);
13353a5a1b3Sopenharmony_ci        fail_unless(mb_b != NULL);
13453a5a1b3Sopenharmony_ci        r = pa_memexport_put(export_b, mb_b, &mem_type, &id, &shm_id, &offset, &size);
13553a5a1b3Sopenharmony_ci        fail_unless(r >= 0);
13653a5a1b3Sopenharmony_ci        fail_unless(shm_id == id_a || shm_id == id_b);
13753a5a1b3Sopenharmony_ci        pa_memblock_unref(mb_b);
13853a5a1b3Sopenharmony_ci
13953a5a1b3Sopenharmony_ci        pa_log("B: Memory block exported as %u", id);
14053a5a1b3Sopenharmony_ci
14153a5a1b3Sopenharmony_ci        mb_c = pa_memimport_get(import_c, PA_MEM_TYPE_SHARED_POSIX, id, shm_id, offset, size, false);
14253a5a1b3Sopenharmony_ci        fail_unless(mb_c != NULL);
14353a5a1b3Sopenharmony_ci        x = pa_memblock_acquire(mb_c);
14453a5a1b3Sopenharmony_ci        pa_log_debug("1 data=%s", x);
14553a5a1b3Sopenharmony_ci        pa_memblock_release(mb_c);
14653a5a1b3Sopenharmony_ci
14753a5a1b3Sopenharmony_ci        print_stats(pool_a, "A");
14853a5a1b3Sopenharmony_ci        print_stats(pool_b, "B");
14953a5a1b3Sopenharmony_ci        print_stats(pool_c, "C");
15053a5a1b3Sopenharmony_ci
15153a5a1b3Sopenharmony_ci        pa_memexport_free(export_b);
15253a5a1b3Sopenharmony_ci        x = pa_memblock_acquire(mb_c);
15353a5a1b3Sopenharmony_ci        pa_log_debug("2 data=%s", x);
15453a5a1b3Sopenharmony_ci        pa_memblock_release(mb_c);
15553a5a1b3Sopenharmony_ci        pa_memblock_unref(mb_c);
15653a5a1b3Sopenharmony_ci
15753a5a1b3Sopenharmony_ci        pa_memimport_free(import_b);
15853a5a1b3Sopenharmony_ci
15953a5a1b3Sopenharmony_ci        pa_memblock_unref(mb_a);
16053a5a1b3Sopenharmony_ci
16153a5a1b3Sopenharmony_ci        pa_memimport_free(import_c);
16253a5a1b3Sopenharmony_ci        pa_memexport_free(export_a);
16353a5a1b3Sopenharmony_ci    }
16453a5a1b3Sopenharmony_ci
16553a5a1b3Sopenharmony_ci    pa_log("vacuuming...");
16653a5a1b3Sopenharmony_ci
16753a5a1b3Sopenharmony_ci    pa_mempool_vacuum(pool_a);
16853a5a1b3Sopenharmony_ci    pa_mempool_vacuum(pool_b);
16953a5a1b3Sopenharmony_ci    pa_mempool_vacuum(pool_c);
17053a5a1b3Sopenharmony_ci
17153a5a1b3Sopenharmony_ci    pa_log("vacuuming done...");
17253a5a1b3Sopenharmony_ci
17353a5a1b3Sopenharmony_ci    pa_mempool_unref(pool_a);
17453a5a1b3Sopenharmony_ci    pa_mempool_unref(pool_b);
17553a5a1b3Sopenharmony_ci    pa_mempool_unref(pool_c);
17653a5a1b3Sopenharmony_ci}
17753a5a1b3Sopenharmony_ciEND_TEST
17853a5a1b3Sopenharmony_ci
17953a5a1b3Sopenharmony_ciint main(int argc, char *argv[]) {
18053a5a1b3Sopenharmony_ci    int failed = 0;
18153a5a1b3Sopenharmony_ci    Suite *s;
18253a5a1b3Sopenharmony_ci    TCase *tc;
18353a5a1b3Sopenharmony_ci    SRunner *sr;
18453a5a1b3Sopenharmony_ci
18553a5a1b3Sopenharmony_ci    if (!getenv("MAKE_CHECK"))
18653a5a1b3Sopenharmony_ci        pa_log_set_level(PA_LOG_DEBUG);
18753a5a1b3Sopenharmony_ci
18853a5a1b3Sopenharmony_ci    s = suite_create("Memblock");
18953a5a1b3Sopenharmony_ci    tc = tcase_create("memblock");
19053a5a1b3Sopenharmony_ci    tcase_add_test(tc, memblock_test);
19153a5a1b3Sopenharmony_ci    suite_add_tcase(s, tc);
19253a5a1b3Sopenharmony_ci
19353a5a1b3Sopenharmony_ci    sr = srunner_create(s);
19453a5a1b3Sopenharmony_ci    srunner_run_all(sr, CK_NORMAL);
19553a5a1b3Sopenharmony_ci    failed = srunner_ntests_failed(sr);
19653a5a1b3Sopenharmony_ci    srunner_free(sr);
19753a5a1b3Sopenharmony_ci
19853a5a1b3Sopenharmony_ci    return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
19953a5a1b3Sopenharmony_ci}
200