<atlka@pg.gda.pl>

- shm memory patch
- optimized a bit sample mixing routines in c and x_86 asm
This commit is contained in:
Jaroslav Kysela 2004-01-24 16:34:35 +00:00
parent 0f88788f8b
commit b798d89c0f
5 changed files with 86 additions and 83 deletions

View File

@ -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); static int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix);
struct shmid_ds buf; 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); dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t), IPC_CREAT | 0666);
if (dmix->shmid < 0) err = -errno;
return -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); dmix->shmptr = shmat(dmix->shmid, 0, 0);
if (dmix->shmptr == (void *) -1) { if (dmix->shmptr == (void *) -1) {
snd_pcm_direct_shm_discard(dmix); 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 */ if (buf.shm_nattch == 1) { /* we're the first user, clear the segment */
memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t)); 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) int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix)

View File

@ -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_create_or_connect(snd_pcm_direct_t *dmix)
{ {
static int shm_sum_discard(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_t size;
size = dmix->shmptr->s.channels * size = dmix->shmptr->s.channels *
dmix->shmptr->s.buffer_size * dmix->shmptr->s.buffer_size *
sizeof(signed int); sizeof(signed int);
retryshm:
dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size, IPC_CREAT | 0666); dmix->u.dmix.shmid_sum = shmget(dmix->ipc_key + 1, size, IPC_CREAT | 0666);
if (dmix->u.dmix.shmid_sum < 0) err = -errno;
return -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); dmix->u.dmix.sum_buffer = shmat(dmix->u.dmix.shmid_sum, 0, 0);
if (dmix->u.dmix.sum_buffer == (void *) -1) { if (dmix->u.dmix.sum_buffer == (void *) -1) {
shm_sum_discard(dmix); shm_sum_discard(dmix);
@ -214,7 +226,7 @@ static void mix_areas1(unsigned int size,
{ {
register signed int sample, old_sample; register signed int sample, old_sample;
while (size-- > 0) { for (;;) {
sample = *src; sample = *src;
old_sample = *sum; old_sample = *sum;
if (*dst == 0) if (*dst == 0)
@ -230,6 +242,8 @@ static void mix_areas1(unsigned int size,
sample = old_sample; sample = old_sample;
*dst = sample; *dst = sample;
} while (*sum != old_sample); } while (*sum != old_sample);
if (!--size)
return;
((char *)src) += src_step; ((char *)src) += src_step;
((char *)dst) += dst_step; ((char *)dst) += dst_step;
((char *)sum) += sum_step; ((char *)sum) += sum_step;
@ -244,7 +258,7 @@ static void mix_areas2(unsigned int size,
{ {
register signed int sample, old_sample; register signed int sample, old_sample;
while (size-- > 0) { for (;;) {
sample = *src / 256; sample = *src / 256;
old_sample = *sum; old_sample = *sum;
if (*dst == 0) if (*dst == 0)
@ -260,6 +274,8 @@ static void mix_areas2(unsigned int size,
sample = old_sample * 256; sample = old_sample * 256;
*dst = sample; *dst = sample;
} while (*sum != old_sample); } while (*sum != old_sample);
if (!--size)
return;
((char *)src) += src_step; ((char *)src) += src_step;
((char *)dst) += dst_step; ((char *)dst) += dst_step;
((char *)sum) += sum_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; dmix->slave_appl_ptr %= dmix->shmptr->s.boundary;
while (size > 0) { while (size > 0) {
transfer = appl_ptr + size > pcm->buffer_size ? pcm->buffer_size - appl_ptr : size; 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; if ((transfer = slave_appl_ptr + transfer > dmix->shmptr->s.buffer_size ? dmix->shmptr->s.buffer_size - slave_appl_ptr : transfer))
size -= transfer;
mix_areas(dmix, src_areas, dst_areas, appl_ptr, 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 += transfer;
slave_appl_ptr %= dmix->shmptr->s.buffer_size; slave_appl_ptr %= dmix->shmptr->s.buffer_size;
appl_ptr += transfer; appl_ptr += transfer;

View File

@ -51,16 +51,17 @@ static void MIX_AREAS1(unsigned int size,
"\tmovl %1, %%edi\n" "\tmovl %1, %%edi\n"
"\tmovl %2, %%esi\n" "\tmovl %2, %%esi\n"
"\tmovl %3, %%ebx\n" "\tmovl %3, %%ebx\n"
"\tjmp 2f\n"
/* /*
* while (size-- > 0) { * for (;;)
*/ */
"\tcmpl $0, %0\n"
"jz 6f\n"
"\t.p2align 4,,15\n" "\t.p2align 4,,15\n"
"1:" "1:"
"\tadd %4, %%edi\n"
"\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n"
/* /*
* sample = *src; * sample = *src;
@ -69,14 +70,17 @@ static void MIX_AREAS1(unsigned int size,
* sample -= sum_sample; * sample -= sum_sample;
* xadd(*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" "\tmovl (%%ebx), %%edx\n"
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n" "\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n"
"\tmovswl (%%esi), %%ecx\n" "\tmovswl (%%esi), %%ecx\n"
"\tjnz 2f\n" "\tjnz 3f\n"
"\tsubl %%edx, %%ecx\n" "\tsubl %%edx, %%ecx\n"
"2:" "3:"
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n" "\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
/* /*
@ -87,25 +91,22 @@ static void MIX_AREAS1(unsigned int size,
* } while (v != *sum); * } while (v != *sum);
*/ */
"3:" "4:"
"\tmovl (%%ebx), %%ecx\n" "\tmovl (%%ebx), %%ecx\n"
"\tcmpl $0x7fff,%%ecx\n" "\tcmpl $0x7fff,%%ecx\n"
"\tjg 4f\n" "\tjg 5f\n"
"\tcmpl $-0x8000,%%ecx\n" "\tcmpl $-0x8000,%%ecx\n"
"\tjl 5f\n" "\tjl 6f\n"
"\tmovw %%cx, (%%edi)\n" "\tmovw %%cx, (%%edi)\n"
"\tcmpl %%ecx, (%%ebx)\n" "\tcmpl %%ecx, (%%ebx)\n"
"\tjnz 3b\n" "\tjnz 4b\n"
/* /*
* while (size-- > 0) * while (size-- > 0)
*/ */
"\tadd %4, %%edi\n"
"\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n"
"\tdecl %0\n" "\tdecl %0\n"
"\tjnz 1b\n" "\tjz 7f\n"
"\tjmp 6f\n" "\tjmp 1b\n"
/* /*
* sample > 0x7fff * sample > 0x7fff
@ -113,16 +114,13 @@ static void MIX_AREAS1(unsigned int size,
"\t.p2align 4,,15\n" "\t.p2align 4,,15\n"
"4:" "5:"
"\tmovw $0x7fff, (%%edi)\n" "\tmovw $0x7fff, (%%edi)\n"
"\tcmpl %%ecx,(%%ebx)\n" "\tcmpl %%ecx,(%%ebx)\n"
"\tjnz 3b\n" "\tjnz 4b\n"
"\tadd %4, %%edi\n"
"\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n"
"\tdecl %0\n" "\tdecl %0\n"
"\tjnz 1b\n" "\tjnz 1b\n"
"\tjmp 6f\n" "\tjmp 7f\n"
/* /*
* sample < -0x8000 * sample < -0x8000
@ -130,18 +128,15 @@ static void MIX_AREAS1(unsigned int size,
"\t.p2align 4,,15\n" "\t.p2align 4,,15\n"
"5:" "6:"
"\tmovw $-0x8000, (%%edi)\n" "\tmovw $-0x8000, (%%edi)\n"
"\tcmpl %%ecx, (%%ebx)\n" "\tcmpl %%ecx, (%%ebx)\n"
"\tjnz 3b\n" "\tjnz 4b\n"
"\tadd %4, %%edi\n"
"\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n"
"\tdecl %0\n" "\tdecl %0\n"
"\tjnz 1b\n" "\tjnz 1b\n"
// "\tjmp 6f\n" // "\tjmp 6f\n"
"6:" "7:"
: /* no output regs */ : /* no output regs */
: "m" (size), "m" (dst), "m" (src), "m" (sum), "m" (dst_step), "m" (src_step), "m" (sum_step) : "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 %1, %%edi\n"
"\tmovl %2, %%esi\n" "\tmovl %2, %%esi\n"
"\tmovl %3, %%ebx\n" "\tmovl %3, %%ebx\n"
"\tjmp 2f\n"
/*
* while (size-- > 0) {
*/
"\tcmpl $0, %0\n"
"jz 6f\n"
"\t.p2align 4,,15\n" "\t.p2align 4,,15\n"
"1:" "1:"
"\tadd %4, %%edi\n"
"\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n"
"2:"
/* /*
* sample = *src; * sample = *src;
* sum_sample = *sum; * sum_sample = *sum;
@ -192,14 +185,15 @@ static void MIX_AREAS1_MMX(unsigned int size,
* sample -= sum_sample; * sample -= sum_sample;
* xadd(*sum, sample); * xadd(*sum, sample);
*/ */
"\tmovw $0, %%ax\n" "\txor %%ax, %%ax\n"
"\tmovw $1, %%cx\n" "\tmovw %%ax, %%cx\n"
"\tincw %%cx\n"
"\tmovl (%%ebx), %%edx\n" "\tmovl (%%ebx), %%edx\n"
"\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n" "\t" LOCK_PREFIX "cmpxchgw %%cx, (%%edi)\n"
"\tmovswl (%%esi), %%ecx\n" "\tmovswl (%%esi), %%ecx\n"
"\tjnz 2f\n" "\tjnz 3f\n"
"\tsubl %%edx, %%ecx\n" "\tsubl %%edx, %%ecx\n"
"2:" "3:"
"\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n" "\t" LOCK_PREFIX "addl %%ecx, (%%ebx)\n"
/* /*
@ -210,27 +204,20 @@ static void MIX_AREAS1_MMX(unsigned int size,
* } while (v != *sum); * } while (v != *sum);
*/ */
"3:" "4:"
"\tmovl (%%ebx), %%ecx\n" "\tmovl (%%ebx), %%ecx\n"
"\tmovd %%ecx, %%mm0\n" "\tmovd %%ecx, %%mm0\n"
"\tpackssdw %%mm1, %%mm0\n" "\tpackssdw %%mm1, %%mm0\n"
"\tmovd %%mm0, %%eax\n" "\tmovd %%mm0, %%eax\n"
"\tmovw %%ax, (%%edi)\n" "\tmovw %%ax, (%%edi)\n"
"\tcmpl %%ecx, (%%ebx)\n" "\tcmpl %%ecx, (%%ebx)\n"
"\tjnz 3b\n" "\tjnz 4b\n"
/* /*
* while (size-- > 0) * while (size-- > 0)
*/ */
"\tadd %4, %%edi\n"
"\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n"
"\tdecl %0\n" "\tdecl %0\n"
"\tjnz 1b\n" "\tjnz 1b\n"
"\tjmp 6f\n"
"6:"
"\temms\n" "\temms\n"
: /* no output regs */ : /* no output regs */
@ -265,12 +252,6 @@ static void MIX_AREAS2(unsigned int size,
"\tmovl %2, %%esi\n" "\tmovl %2, %%esi\n"
"\tmovl %3, %%ebx\n" "\tmovl %3, %%ebx\n"
/*
* while (size-- > 0) {
*/
"\tcmpl $0, %0\n"
"jz 6f\n"
"\t.p2align 4,,15\n" "\t.p2align 4,,15\n"
"1:" "1:"
@ -334,12 +315,12 @@ static void MIX_AREAS2(unsigned int size,
/* /*
* while (size-- > 0) * while (size-- > 0)
*/ */
"\tdecl %0\n"
"\tjz 6f\n"
"\tadd %4, %%edi\n" "\tadd %4, %%edi\n"
"\tadd %5, %%esi\n" "\tadd %5, %%esi\n"
"\tadd %6, %%ebx\n" "\tadd %6, %%ebx\n"
"\tdecl %0\n" "\tjmp 1b\n"
"\tjnz 1b\n"
// "\tjmp 6f\n"
"6:" "6:"
: /* no output regs */ : /* no output regs */

View File

@ -368,6 +368,11 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
SYSERR("shmat failed"); SYSERR("shmat failed");
return -errno; 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); i->u.shm.area = snd_shm_area_create(id, ptr);
if (i->u.shm.area == NULL) { if (i->u.shm.area == NULL) {
SYSERR("snd_shm_area_create failed"); SYSERR("snd_shm_area_create failed");

View File

@ -56,17 +56,6 @@ struct snd_shm_area *snd_shm_area_share(struct snd_shm_area *area)
return 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) int snd_shm_area_destroy(struct snd_shm_area *area)
{ {
if (area == NULL) if (area == NULL)
@ -74,7 +63,7 @@ int snd_shm_area_destroy(struct snd_shm_area *area)
if (--area->share) if (--area->share)
return 0; return 0;
list_del(&area->list); list_del(&area->list);
_x_destroy(area); shmdt(area->ptr);
free(area); free(area);
return 0; return 0;
} }
@ -88,6 +77,6 @@ void snd_shm_area_destructor(void)
list_for_each(pos, &shm_areas) { list_for_each(pos, &shm_areas) {
area = list_entry(pos, struct snd_shm_area, list); area = list_entry(pos, struct snd_shm_area, list);
_x_destroy(area); shmdt(area->ptr);
} }
} }