mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	<atlka@pg.gda.pl>
- shm memory patch - optimized a bit sample mixing routines in c and x_86 asm
This commit is contained in:
		
							parent
							
								
									0f88788f8b
								
							
						
					
					
						commit
						b798d89c0f
					
				
					 5 changed files with 86 additions and 83 deletions
				
			
		| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue