int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
{
- struct sembuf op[2] = { { 0, 0, SEM_UNDO }, { 0, 1, SEM_UNDO | IPC_NOWAIT } };
+ struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
assert(dmix->semid >= 0);
- op[0].sem_num = sem_num;
- op[1].sem_num = sem_num;
if (semop(dmix->semid, op, 2) < 0)
return -errno;
return 0;
int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
{
- struct sembuf op = { 0, -1, SEM_UNDO | IPC_NOWAIT };
+ struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
assert(dmix->semid >= 0);
- op.sem_num = sem_num;
if (semop(dmix->semid, &op, 1) < 0)
return -errno;
return 0;
snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
snd_pcm_direct_shm_discard(dmix);
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
continue;
}
server_printf("DIRECT SERVER: nattch = %i\n", (int)buf.shm_nattch);
if (dmix->client)
snd_pcm_direct_client_discard(dmix);
shm_sum_discard(dmix);
- if (snd_pcm_direct_shm_discard(dmix) > 0) {
- if (snd_pcm_direct_semaphore_discard(dmix) < 0)
- snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
- } else {
- snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
- }
+ snd_pcm_direct_shm_discard(dmix);
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
if (dmix->bindings)
free(dmix->bindings);
pcm->private_data = NULL;
dmix = calloc(1, sizeof(snd_pcm_direct_t));
if (!dmix) {
ret = -ENOMEM;
- goto _err;
+ goto _err_nosem;
}
ret = snd_pcm_direct_parse_bindings(dmix, bindings);
if (ret < 0)
- goto _err;
+ goto _err_nosem;
dmix->ipc_key = ipc_key;
dmix->ipc_perm = ipc_perm;
ret = snd_pcm_direct_semaphore_create_or_connect(dmix);
if (ret < 0) {
SNDERR("unable to create IPC semaphore");
- goto _err;
+ goto _err_nosem;
}
ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
if (ret < 0) {
snd_pcm_direct_semaphore_discard(dmix);
if (--fail_sem_loop <= 0)
- goto _err;
+ goto _err_nosem;
continue;
}
break;
dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
if (first_instance) {
- ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+ ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode | SND_PCM_NONBLOCK);
if (ret < 0) {
SNDERR("unable to open slave");
goto _err;
dmix->shmptr->type = spcm->type;
} else {
+ /* up semaphore to avoid deadlock */
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_direct_client_connect(dmix);
if (ret < 0) {
SNDERR("unable to connect client");
- return ret;
+ goto _err_nosem;
}
+ snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_hw_open_fd(&spcm, "dmix_client", dmix->hw_fd, 0, 0);
if (ret < 0) {
SNDERR("unable to open hardware");
return 0;
_err:
+ if (dmix->timer)
+ snd_timer_close(dmix->timer);
+ if (dmix->server)
+ snd_pcm_direct_server_discard(dmix);
+ if (dmix->client)
+ snd_pcm_direct_client_discard(dmix);
+ if (spcm)
+ snd_pcm_close(spcm);
+ if (dmix->u.dmix.shmid_sum >= 0)
+ shm_sum_discard(dmix);
+ if (dmix->shmid >= 0)
+ snd_pcm_direct_shm_discard(dmix);
+ if (snd_pcm_direct_semaphore_discard(dmix) < 0)
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
+ _err_nosem:
if (dmix) {
- if (dmix->timer)
- snd_timer_close(dmix->timer);
- if (dmix->server)
- snd_pcm_direct_server_discard(dmix);
- if (dmix->client)
- snd_pcm_direct_client_discard(dmix);
- if (spcm)
- snd_pcm_close(spcm);
- if (dmix->u.dmix.shmid_sum >= 0)
- shm_sum_discard(dmix);
- if (dmix->shmid >= 0) {
- if (snd_pcm_direct_shm_discard(dmix) > 0) {
- if (dmix->semid >= 0) {
- if (snd_pcm_direct_semaphore_discard(dmix) < 0)
- snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
- }
- }
- }
- if (dmix->bindings)
- free(dmix->bindings);
+ if (dmix->bindings)
+ free(dmix->bindings);
free(dmix);
}
if (pcm)
snd_pcm_direct_server_discard(dshare);
if (dshare->client)
snd_pcm_direct_client_discard(dshare);
- if (snd_pcm_direct_shm_discard(dshare) > 0) {
- if (snd_pcm_direct_semaphore_discard(dshare) < 0)
- snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
- } else {
- snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
- }
+ snd_pcm_direct_shm_discard(dshare);
+ snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
if (dshare->bindings)
free(dshare->bindings);
pcm->private_data = NULL;
dshare = calloc(1, sizeof(snd_pcm_direct_t));
if (!dshare) {
ret = -ENOMEM;
- goto _err;
+ goto _err_nosem;
}
ret = snd_pcm_direct_parse_bindings(dshare, bindings);
if (ret < 0)
- goto _err;
+ goto _err_nosem;
if (!dshare->bindings) {
SNDERR("dshare: specify bindings!!!");
ret = -EINVAL;
- goto _err;
+ goto _err_nosem;
}
dshare->ipc_key = ipc_key;
ret = snd_pcm_new(&pcm, dshare->type = SND_PCM_TYPE_DSHARE, name, stream, mode);
if (ret < 0)
- goto _err;
+ goto _err_nosem;
while (1) {
ret = snd_pcm_direct_semaphore_create_or_connect(dshare);
if (ret < 0) {
SNDERR("unable to create IPC semaphore");
- goto _err;
+ goto _err_nosem;
}
ret = snd_pcm_direct_semaphore_down(dshare, DIRECT_IPC_SEM_CLIENT);
if (ret < 0) {
snd_pcm_direct_semaphore_discard(dshare);
if (--fail_sem_loop <= 0)
- goto _err;
+ goto _err_nosem;
continue;
}
break;
dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
if (first_instance) {
- ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+ ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode | SND_PCM_NONBLOCK);
if (ret < 0) {
SNDERR("unable to open slave");
goto _err;
dshare->shmptr->type = spcm->type;
} else {
+ /* up semaphore to avoid deadlock */
+ snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_direct_client_connect(dshare);
if (ret < 0) {
SNDERR("unable to connect client");
- return ret;
+ goto _err_nosem;
}
+ snd_pcm_direct_semaphore_down(dshare, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_hw_open_fd(&spcm, "dshare_client", dshare->hw_fd, 0, 0);
if (ret < 0) {
SNDERR("unable to open hardware");
return 0;
_err:
+ if (dshare->shmptr)
+ dshare->shmptr->u.dshare.chn_mask &= ~dshare->u.dshare.chn_mask;
+ if (dshare->timer)
+ snd_timer_close(dshare->timer);
+ if (dshare->server)
+ snd_pcm_direct_server_discard(dshare);
+ if (dshare->client)
+ snd_pcm_direct_client_discard(dshare);
+ if (spcm)
+ snd_pcm_close(spcm);
+ if (dshare->shmid >= 0)
+ snd_pcm_direct_shm_discard(dshare);
+ if (snd_pcm_direct_semaphore_discard(dshare) < 0)
+ snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
+ _err_nosem:
if (dshare) {
- if (dshare->shmptr)
- dshare->shmptr->u.dshare.chn_mask &= ~dshare->u.dshare.chn_mask;
- if (dshare->timer)
- snd_timer_close(dshare->timer);
- if (dshare->server)
- snd_pcm_direct_server_discard(dshare);
- if (dshare->client)
- snd_pcm_direct_client_discard(dshare);
- if (spcm)
- snd_pcm_close(spcm);
- if (dshare->shmid >= 0) {
- if (snd_pcm_direct_shm_discard(dshare) > 0) {
- if (dshare->semid >= 0) {
- if (snd_pcm_direct_semaphore_discard(dshare) < 0)
- snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
- }
- }
- }
- if (dshare->bindings)
- free(dshare->bindings);
+ if (dshare->bindings)
+ free(dshare->bindings);
free(dshare);
}
if (pcm)
snd_pcm_direct_server_discard(dsnoop);
if (dsnoop->client)
snd_pcm_direct_client_discard(dsnoop);
- if (snd_pcm_direct_shm_discard(dsnoop) > 0) {
- if (snd_pcm_direct_semaphore_discard(dsnoop) < 0)
- snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
- } else {
- snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
- }
+ snd_pcm_direct_shm_discard(dsnoop);
+ snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
if (dsnoop->bindings)
free(dsnoop->bindings);
pcm->private_data = NULL;
dsnoop = calloc(1, sizeof(snd_pcm_direct_t));
if (!dsnoop) {
ret = -ENOMEM;
- goto _err;
+ goto _err_nosem;
}
ret = snd_pcm_direct_parse_bindings(dsnoop, bindings);
if (ret < 0)
- goto _err;
+ goto _err_nosem;
dsnoop->ipc_key = ipc_key;
dsnoop->ipc_perm = ipc_perm;
ret = snd_pcm_new(&pcm, dsnoop->type = SND_PCM_TYPE_DSNOOP, name, stream, mode);
if (ret < 0)
- goto _err;
+ goto _err_nosem;
while (1) {
ret = snd_pcm_direct_semaphore_create_or_connect(dsnoop);
if (ret < 0) {
SNDERR("unable to create IPC semaphore");
- goto _err;
+ goto _err_nosem;
}
ret = snd_pcm_direct_semaphore_down(dsnoop, DIRECT_IPC_SEM_CLIENT);
if (ret < 0) {
snd_pcm_direct_semaphore_discard(dsnoop);
if (--fail_sem_loop <= 0)
- goto _err;
+ goto _err_nosem;
continue;
}
break;
dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
if (first_instance) {
- ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+ ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode | SND_PCM_NONBLOCK);
if (ret < 0) {
SNDERR("unable to open slave");
goto _err;
dsnoop->shmptr->type = spcm->type;
} else {
+ /* up semaphore to avoid deadlock */
+ snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_direct_client_connect(dsnoop);
if (ret < 0) {
SNDERR("unable to connect client");
- return ret;
+ goto _err_nosem;
}
+ snd_pcm_direct_semaphore_down(dsnoop, DIRECT_IPC_SEM_CLIENT);
ret = snd_pcm_hw_open_fd(&spcm, "dsnoop_client", dsnoop->hw_fd, 0, 0);
if (ret < 0) {
SNDERR("unable to open hardware");
return 0;
_err:
+ if (dsnoop->timer)
+ snd_timer_close(dsnoop->timer);
+ if (dsnoop->server)
+ snd_pcm_direct_server_discard(dsnoop);
+ if (dsnoop->client)
+ snd_pcm_direct_client_discard(dsnoop);
+ if (spcm)
+ snd_pcm_close(spcm);
+ if (dsnoop->shmid >= 0)
+ snd_pcm_direct_shm_discard(dsnoop);
+ if (snd_pcm_direct_semaphore_discard(dsnoop) < 0)
+ snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
+ _err_nosem:
if (dsnoop) {
- if (dsnoop->timer)
- snd_timer_close(dsnoop->timer);
- if (dsnoop->server)
- snd_pcm_direct_server_discard(dsnoop);
- if (dsnoop->client)
- snd_pcm_direct_client_discard(dsnoop);
- if (spcm)
- snd_pcm_close(spcm);
- if (dsnoop->shmid >= 0) {
- if (snd_pcm_direct_shm_discard(dsnoop) > 0) {
- if (dsnoop->semid >= 0) {
- if (snd_pcm_direct_semaphore_discard(dsnoop) < 0)
- snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
- }
- }
- }
- if (dsnoop->bindings)
- free(dsnoop->bindings);
+ if (dsnoop->bindings)
+ free(dsnoop->bindings);
free(dsnoop);
}
if (pcm)