From b798d89c0f680dbb708d66839e46571ea47db445 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sat, 24 Jan 2004 16:34:35 +0000 Subject: [PATCH] - shm memory patch - optimized a bit sample mixing routines in c and x_86 asm --- src/pcm/pcm_direct.c | 20 ++++++--- src/pcm/pcm_dmix.c | 30 ++++++++++--- src/pcm/pcm_dmix_i386.h | 99 +++++++++++++++++------------------------ src/pcm/pcm_mmap.c | 5 +++ src/shmarea.c | 15 +------ 5 files changed, 86 insertions(+), 83 deletions(-) diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 44fada7f..12a8f0db 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -101,11 +101,21 @@ int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix) { static int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix); struct shmid_ds buf; - int ret = 0; + int tmpid, err; +retryget: dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t), IPC_CREAT | 0666); - if (dmix->shmid < 0) - return -errno; + err = -errno; + if (dmix->shmid < 0){ + if (errno == EINVAL) + if ((tmpid = shmget(dmix->ipc_key, 0, 0666)) != -1) + if (!shmctl(tmpid, IPC_STAT, &buf)) + if (!buf.shm_nattch) + /* no users so destroy the segment */ + if (!shmctl(tmpid, IPC_RMID, NULL)) + goto retryget; + return err; + } dmix->shmptr = shmat(dmix->shmid, 0, 0); if (dmix->shmptr == (void *) -1) { snd_pcm_direct_shm_discard(dmix); @@ -118,9 +128,9 @@ int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix) } if (buf.shm_nattch == 1) { /* we're the first user, clear the segment */ memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t)); - ret = 1; + return 1; } - return ret; + return 0; } int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix) diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 7865cbe4..8473d9c0 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -59,14 +59,26 @@ const char *_snd_module_pcm_dmix = ""; static int shm_sum_create_or_connect(snd_pcm_direct_t *dmix) { static int shm_sum_discard(snd_pcm_direct_t *dmix); + struct shmid_ds buf; + int tmpid, err; size_t size; size = dmix->shmptr->s.channels * dmix->shmptr->s.buffer_size * sizeof(signed int); +retryshm: dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size, IPC_CREAT | 0666); - if (dmix->u.dmix.shmid_sum < 0) - return -errno; + err = -errno; + if (dmix->u.dmix.shmid_sum < 0){ + if (errno == EINVAL) + if ((tmpid = shmget(dmix->ipc_key + 1, 0, 0666)) != -1) + if (!shmctl(tmpid, IPC_STAT, &buf)) + if (!buf.shm_nattch) + /* no users so destroy the segment */ + if (!shmctl(tmpid, IPC_RMID, NULL)) + goto retryshm; + return err; + } dmix->u.dmix.sum_buffer = shmat(dmix->u.dmix.shmid_sum, 0, 0); if (dmix->u.dmix.sum_buffer == (void *) -1) { shm_sum_discard(dmix); @@ -214,7 +226,7 @@ static void mix_areas1(unsigned int size, { register signed int sample, old_sample; - while (size-- > 0) { + for (;;) { sample = *src; old_sample = *sum; if (*dst == 0) @@ -230,6 +242,8 @@ static void mix_areas1(unsigned int size, sample = old_sample; *dst = sample; } while (*sum != old_sample); + if (!--size) + return; ((char *)src) += src_step; ((char *)dst) += dst_step; ((char *)sum) += sum_step; @@ -244,7 +258,7 @@ static void mix_areas2(unsigned int size, { register signed int sample, old_sample; - while (size-- > 0) { + for (;;) { sample = *src / 256; old_sample = *sum; if (*dst == 0) @@ -260,6 +274,8 @@ static void mix_areas2(unsigned int size, sample = old_sample * 256; *dst = sample; } while (*sum != old_sample); + if (!--size) + return; ((char *)src) += src_step; ((char *)dst) += dst_step; ((char *)sum) += sum_step; @@ -366,9 +382,11 @@ static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm, snd_pcm_uframes_t size) dmix->slave_appl_ptr %= dmix->shmptr->s.boundary; while (size > 0) { transfer = appl_ptr + size > pcm->buffer_size ? pcm->buffer_size - appl_ptr : size; - transfer = slave_appl_ptr + transfer > dmix->shmptr->s.buffer_size ? dmix->shmptr->s.buffer_size - slave_appl_ptr : transfer; - size -= transfer; + if ((transfer = slave_appl_ptr + transfer > dmix->shmptr->s.buffer_size ? dmix->shmptr->s.buffer_size - slave_appl_ptr : transfer)) mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer); + if (transfer >= size) + return; + size -= transfer; slave_appl_ptr += transfer; slave_appl_ptr %= dmix->shmptr->s.buffer_size; appl_ptr += transfer; diff --git a/src/pcm/pcm_dmix_i386.h b/src/pcm/pcm_dmix_i386.h index 15a8e714..e104d2e0 100644 --- a/src/pcm/pcm_dmix_i386.h +++ b/src/pcm/pcm_dmix_i386.h @@ -51,16 +51,17 @@ static void MIX_AREAS1(unsigned int size, "\tmovl %1, %%edi\n" "\tmovl %2, %%esi\n" "\tmovl %3, %%ebx\n" + "\tjmp 2f\n" + /* - * while (size-- > 0) { + * for (;;) */ - "\tcmpl $0, %0\n" - "jz 6f\n" - "\t.p2align 4,,15\n" - "1:" + "\tadd %4, %%edi\n" + "\tadd %5, %%esi\n" + "\tadd %6, %%ebx\n" /* * sample = *src; @@ -69,14 +70,17 @@ static void MIX_AREAS1(unsigned int size, * sample -= sum_sample; * xadd(*sum, sample); */ - "\tmovw $0, %%ax\n" - "\tmovw $1, %%cx\n" + + "2:" + "\txor %%ax, %%ax\n" + "\tmovw %%ax, %%cx\n" + "\tincw %%cx\n" "\tmovl (%%ebx), %%edx\n" "\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n" "\tmovswl (%%esi), %%ecx\n" - "\tjnz 2f\n" + "\tjnz 3f\n" "\tsubl %%edx, %%ecx\n" - "2:" + "3:" "\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n" /* @@ -87,25 +91,22 @@ static void MIX_AREAS1(unsigned int size, * } while (v != *sum); */ - "3:" + "4:" "\tmovl (%%ebx), %%ecx\n" "\tcmpl $0x7fff,%%ecx\n" - "\tjg 4f\n" + "\tjg 5f\n" "\tcmpl $-0x8000,%%ecx\n" - "\tjl 5f\n" + "\tjl 6f\n" "\tmovw %%cx, (%%edi)\n" "\tcmpl %%ecx, (%%ebx)\n" - "\tjnz 3b\n" + "\tjnz 4b\n" /* * while (size-- > 0) */ - "\tadd %4, %%edi\n" - "\tadd %5, %%esi\n" - "\tadd %6, %%ebx\n" "\tdecl %0\n" - "\tjnz 1b\n" - "\tjmp 6f\n" + "\tjz 7f\n" + "\tjmp 1b\n" /* * sample > 0x7fff @@ -113,16 +114,13 @@ static void MIX_AREAS1(unsigned int size, "\t.p2align 4,,15\n" - "4:" + "5:" "\tmovw $0x7fff, (%%edi)\n" "\tcmpl %%ecx,(%%ebx)\n" - "\tjnz 3b\n" - "\tadd %4, %%edi\n" - "\tadd %5, %%esi\n" - "\tadd %6, %%ebx\n" + "\tjnz 4b\n" "\tdecl %0\n" "\tjnz 1b\n" - "\tjmp 6f\n" + "\tjmp 7f\n" /* * sample < -0x8000 @@ -130,18 +128,15 @@ static void MIX_AREAS1(unsigned int size, "\t.p2align 4,,15\n" - "5:" + "6:" "\tmovw $-0x8000, (%%edi)\n" "\tcmpl %%ecx, (%%ebx)\n" - "\tjnz 3b\n" - "\tadd %4, %%edi\n" - "\tadd %5, %%esi\n" - "\tadd %6, %%ebx\n" + "\tjnz 4b\n" "\tdecl %0\n" "\tjnz 1b\n" // "\tjmp 6f\n" - "6:" + "7:" : /* no output regs */ : "m" (size), "m" (dst), "m" (src), "m" (sum), "m" (dst_step), "m" (src_step), "m" (sum_step) @@ -174,17 +169,15 @@ static void MIX_AREAS1_MMX(unsigned int size, "\tmovl %1, %%edi\n" "\tmovl %2, %%esi\n" "\tmovl %3, %%ebx\n" - - /* - * while (size-- > 0) { - */ - "\tcmpl $0, %0\n" - "jz 6f\n" + "\tjmp 2f\n" "\t.p2align 4,,15\n" - "1:" + "\tadd %4, %%edi\n" + "\tadd %5, %%esi\n" + "\tadd %6, %%ebx\n" + "2:" /* * sample = *src; * sum_sample = *sum; @@ -192,14 +185,15 @@ static void MIX_AREAS1_MMX(unsigned int size, * sample -= sum_sample; * xadd(*sum, sample); */ - "\tmovw $0, %%ax\n" - "\tmovw $1, %%cx\n" + "\txor %%ax, %%ax\n" + "\tmovw %%ax, %%cx\n" + "\tincw %%cx\n" "\tmovl (%%ebx), %%edx\n" "\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n" "\tmovswl (%%esi), %%ecx\n" - "\tjnz 2f\n" + "\tjnz 3f\n" "\tsubl %%edx, %%ecx\n" - "2:" + "3:" "\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n" /* @@ -210,27 +204,20 @@ static void MIX_AREAS1_MMX(unsigned int size, * } while (v != *sum); */ - "3:" + "4:" "\tmovl (%%ebx), %%ecx\n" "\tmovd %%ecx, %%mm0\n" "\tpackssdw %%mm1, %%mm0\n" "\tmovd %%mm0, %%eax\n" "\tmovw %%ax, (%%edi)\n" "\tcmpl %%ecx, (%%ebx)\n" - "\tjnz 3b\n" + "\tjnz 4b\n" /* * while (size-- > 0) */ - "\tadd %4, %%edi\n" - "\tadd %5, %%esi\n" - "\tadd %6, %%ebx\n" "\tdecl %0\n" "\tjnz 1b\n" - "\tjmp 6f\n" - - "6:" - "\temms\n" : /* no output regs */ @@ -265,12 +252,6 @@ static void MIX_AREAS2(unsigned int size, "\tmovl %2, %%esi\n" "\tmovl %3, %%ebx\n" - /* - * while (size-- > 0) { - */ - "\tcmpl $0, %0\n" - "jz 6f\n" - "\t.p2align 4,,15\n" "1:" @@ -334,12 +315,12 @@ static void MIX_AREAS2(unsigned int size, /* * while (size-- > 0) */ + "\tdecl %0\n" + "\tjz 6f\n" "\tadd %4, %%edi\n" "\tadd %5, %%esi\n" "\tadd %6, %%ebx\n" - "\tdecl %0\n" - "\tjnz 1b\n" - // "\tjmp 6f\n" + "\tjmp 1b\n" "6:" : /* no output regs */ diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index ba3e7c2a..dd30f5c7 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -368,6 +368,11 @@ int snd_pcm_mmap(snd_pcm_t *pcm) SYSERR("shmat failed"); return -errno; } + /* automatically remove segment if not used */ + if (shmctl(id, IPC_RMID, NULL) < 0){ + SYSERR("shmctl mark remove failed"); + return -errno; + } i->u.shm.area = snd_shm_area_create(id, ptr); if (i->u.shm.area == NULL) { SYSERR("snd_shm_area_create failed"); diff --git a/src/shmarea.c b/src/shmarea.c index 53a6533b..0d7d30bd 100644 --- a/src/shmarea.c +++ b/src/shmarea.c @@ -56,17 +56,6 @@ struct snd_shm_area *snd_shm_area_share(struct snd_shm_area *area) return area; } -static void _x_destroy(struct snd_shm_area *area) -{ - struct shmid_ds buf; - - shmdt(area->ptr); - if (shmctl(area->shmid, IPC_STAT, &buf) >= 0) { - if (buf.shm_nattch == 0) - shmctl(area->shmid, IPC_RMID, NULL); - } -} - int snd_shm_area_destroy(struct snd_shm_area *area) { if (area == NULL) @@ -74,7 +63,7 @@ int snd_shm_area_destroy(struct snd_shm_area *area) if (--area->share) return 0; list_del(&area->list); - _x_destroy(area); + shmdt(area->ptr); free(area); return 0; } @@ -88,6 +77,6 @@ void snd_shm_area_destructor(void) list_for_each(pos, &shm_areas) { area = list_entry(pos, struct snd_shm_area, list); - _x_destroy(area); + shmdt(area->ptr); } } -- 2.47.1