Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1935b4d authored by Jaroslav Kysela's avatar Jaroslav Kysela
Browse files

[ALSA] timer - added tread semaphore



Timer Midlevel


Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 54ab87e6
Loading
Loading
Loading
Loading
+37 −20
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ typedef struct {
	struct timespec tstamp;		/* trigger tstamp */
	struct timespec tstamp;		/* trigger tstamp */
	wait_queue_head_t qchange_sleep;
	wait_queue_head_t qchange_sleep;
	struct fasync_struct *fasync;
	struct fasync_struct *fasync;
	struct semaphore tread_sem;
} snd_timer_user_t;
} snd_timer_user_t;


/* list of timers */
/* list of timers */
@@ -1208,6 +1209,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
		return -ENOMEM;
		return -ENOMEM;
	spin_lock_init(&tu->qlock);
	spin_lock_init(&tu->qlock);
	init_waitqueue_head(&tu->qchange_sleep);
	init_waitqueue_head(&tu->qchange_sleep);
	init_MUTEX(&tu->tread_sem);
	tu->ticks = 1;
	tu->ticks = 1;
	tu->queue_size = 128;
	tu->queue_size = 128;
	tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
	tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
@@ -1454,18 +1456,23 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
	snd_timer_user_t *tu;
	snd_timer_user_t *tu;
	snd_timer_select_t tselect;
	snd_timer_select_t tselect;
	char str[32];
	char str[32];
	int err;
	int err = 0;
	
	
	tu = file->private_data;
	tu = file->private_data;
	if (tu->timeri)
	down(&tu->tread_sem);
	if (tu->timeri) {
		snd_timer_close(tu->timeri);
		snd_timer_close(tu->timeri);
	if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
		tu->timeri = NULL;
		return -EFAULT;
	}
	if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
		err = -EFAULT;
		goto __err;
	}
	sprintf(str, "application %i", current->pid);
	sprintf(str, "application %i", current->pid);
	if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
	if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
		tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
		tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
	if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0)
	if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0)
		return err;
		goto __err;


	if (tu->queue) {
	if (tu->queue) {
		kfree(tu->queue);
		kfree(tu->queue);
@@ -1477,23 +1484,27 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
	}
	}
	if (tu->tread) {
	if (tu->tread) {
		tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL);
		tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL);
		if (tu->tqueue == NULL) {
		if (tu->tqueue == NULL)
			snd_timer_close(tu->timeri);
			err = -ENOMEM;
			return -ENOMEM;
		}
	} else {
	} else {
		tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
		tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
		if (tu->queue == NULL) {
		if (tu->queue == NULL)
			snd_timer_close(tu->timeri);
			err = -ENOMEM;
			return -ENOMEM;
		}
	}
	}
	
	
      	if (err < 0) {
		snd_timer_close(tu->timeri);
      		tu->timeri = NULL;
      	} else {
		tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
		tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
		tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
		tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
		tu->timeri->ccallback = snd_timer_user_ccallback;
		tu->timeri->ccallback = snd_timer_user_ccallback;
		tu->timeri->callback_data = (void *)tu;
		tu->timeri->callback_data = (void *)tu;
	return 0;
	}

      __err:
      	up(&tu->tread_sem);
	return err;
}
}


static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
@@ -1685,11 +1696,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
	{
	{
		int xarg;
		int xarg;
		
		
		if (tu->timeri)		/* too late */
		down(&tu->tread_sem);
		if (tu->timeri)	{	/* too late */
			up(&tu->tread_sem);
			return -EBUSY;
			return -EBUSY;
		if (get_user(xarg, p))
		}
		if (get_user(xarg, p)) {
			up(&tu->tread_sem);
			return -EFAULT;
			return -EFAULT;
		}
		tu->tread = xarg ? 1 : 0;
		tu->tread = xarg ? 1 : 0;
		up(&tu->tread_sem);
		return 0;
		return 0;
	}
	}
	case SNDRV_TIMER_IOCTL_GINFO:
	case SNDRV_TIMER_IOCTL_GINFO: