Пример #1
0
static int ach_ch_open(struct inode *inode, struct file *file)
{
    int ret = 0;
    struct ach_ch_device *device;

    /* Synchronize to protect refcounting */
    if (rt_mutex_lock_interruptible(&ctrl_data.lock)) {
        ret = -ERESTARTSYS;
        goto out;
    }

    device = &ctrl_data.devices[iminor(inode)];

    if (unlikely(device->minor != iminor(inode))) {
        printk(KERN_ERR "ach: Internal data problem\n");
        ret = -ERESTARTSYS;
        goto out_unlock;
    }

    file->private_data = ach_ch_file_alloc(device);

    if (!file->private_data) {
        printk(KERN_ERR "ach: Failed allocating file data\n");
        ret = -ENOBUFS;
        goto out_unlock;
    }

    KDEBUG( "ach: opened device %s\n", ach_ch_device_name(device) );

out_unlock:
    rt_mutex_unlock(&ctrl_data.lock);
out:
    return ret;
}
Пример #2
0
int  rt_down_interruptible(struct semaphore *sem)
{
	int ret;

	ret = rt_mutex_lock_interruptible(&sem->lock, 0);
	if (ret)
		return ret;
	__down_complete(sem);
	return 0;
}
Пример #3
0
int __lockfunc _mutex_lock_interruptible_nested(struct mutex *lock, int subclass)
{
	int ret;

	mutex_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
	ret = rt_mutex_lock_interruptible(&lock->lock, 0);
	if (ret)
		mutex_release(&lock->dep_map, 1, _RET_IP_);
	return ret;
}
Пример #4
0
static enum ach_status
chan_lock( ach_channel_t *chan )
{
    int i = rt_mutex_lock_interruptible(&chan->shm->sync.mutex);
    if( -EINTR == i ) return ACH_EINTR;
    if( i ) return ACH_BUG;
    if( chan->cancel ) {
        rt_mutex_unlock(&chan->shm->sync.mutex);
        return ACH_CANCELED;
    }
    if( chan->shm->sync.dirty ) {
        rt_mutex_unlock(&chan->shm->sync.mutex);
        ACH_ERRF("ach bug: channel dirty on lock acquisition\n");
        return ACH_CORRUPT;
    }
    return ACH_OK;
}
Пример #5
0
/**********************************************************************************
 * ach channel device driver
 **********************************************************************************/
static int ach_ch_close(struct inode *inode, struct file *file)
{
    struct ach_ch_file *ch_file;
    int ret = 0;

    KDEBUG("ach: in ach_ch_close (inode %d)\n", iminor(inode));

    /* Synchronize to protect refcounting */
    if (rt_mutex_lock_interruptible(&ctrl_data.lock)) {
        ret = -ERESTARTSYS;
        goto out;
    }

    ch_file = (struct ach_ch_file *)file->private_data;
    kref_put( &ch_file->shm->refcount, ach_shm_release );
    kfree(ch_file);

    rt_mutex_unlock(&ctrl_data.lock);

out:
    return ret;
}
Пример #6
0
static int handle_op(struct test_thread_data *td, int lockwakeup)
{
	int i, id, ret = -EINVAL;

	switch(td->opcode) {

	case RTTEST_NOP:
		return 0;

	case RTTEST_LOCKCONT:
		td->mutexes[td->opdata] = 1;
		td->event = atomic_add_return(1, &rttest_event);
		return 0;

	case RTTEST_RESET:
		for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) {
			if (td->mutexes[i] == 4) {
				rt_mutex_unlock(&mutexes[i]);
				td->mutexes[i] = 0;
			}
		}

		if (!lockwakeup && td->bkl == 4) {
#ifdef CONFIG_LOCK_KERNEL
			unlock_kernel();
#endif
			td->bkl = 0;
		}
		return 0;

	case RTTEST_RESETEVENT:
		atomic_set(&rttest_event, 0);
		return 0;

	default:
		if (lockwakeup)
			return ret;
	}

	switch(td->opcode) {

	case RTTEST_LOCK:
	case RTTEST_LOCKNOWAIT:
		id = td->opdata;
		if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
			return ret;

		td->mutexes[id] = 1;
		td->event = atomic_add_return(1, &rttest_event);
		rt_mutex_lock(&mutexes[id]);
		td->event = atomic_add_return(1, &rttest_event);
		td->mutexes[id] = 4;
		return 0;

	case RTTEST_LOCKINT:
	case RTTEST_LOCKINTNOWAIT:
		id = td->opdata;
		if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
			return ret;

		td->mutexes[id] = 1;
		td->event = atomic_add_return(1, &rttest_event);
		ret = rt_mutex_lock_interruptible(&mutexes[id], 0);
		td->event = atomic_add_return(1, &rttest_event);
		td->mutexes[id] = ret ? 0 : 4;
		return ret ? -EINTR : 0;

	case RTTEST_UNLOCK:
		id = td->opdata;
		if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4)
			return ret;

		td->event = atomic_add_return(1, &rttest_event);
		rt_mutex_unlock(&mutexes[id]);
		td->event = atomic_add_return(1, &rttest_event);
		td->mutexes[id] = 0;
		return 0;

	case RTTEST_LOCKBKL:
		if (td->bkl)
			return 0;
		td->bkl = 1;
#ifdef CONFIG_LOCK_KERNEL
		lock_kernel();
#endif
		td->bkl = 4;
		return 0;

	case RTTEST_UNLOCKBKL:
		if (td->bkl != 4)
			break;
#ifdef CONFIG_LOCK_KERNEL
		unlock_kernel();
#endif
		td->bkl = 0;
		return 0;

	default:
		break;
	}
	return ret;
}
Пример #7
0
static long ach_ctrl_ioctl(struct file *file, unsigned int cmd,
                           unsigned long arg)
{
    /* TODO: Validate argument */
    int ret = 0;

    if (rt_mutex_lock_interruptible(&ctrl_data.lock)) {
        return -ERESTARTSYS;
    }

    switch (cmd) {

    case ACH_CTRL_CREATE_CH: {
        struct ach_ctrl_create_ch create_arg;
        KDEBUG("ach: Control command create\n");
        if (copy_from_user(&create_arg, (void*)arg, sizeof(create_arg)) ) {
            ret = -EFAULT;
        } else if ( strnlen(create_arg.name,ACH_CHAN_NAME_MAX)
                    >= ACH_CHAN_NAME_MAX ) {
            ret = -ENAMETOOLONG;
        } else {
            ret = ctrl_create( &create_arg );
        }
        break;
    }
    case ACH_CTRL_UNLINK_CH: {
        struct ach_ctrl_unlink_ch unlink_arg;
        KDEBUG("ach: Control command unlink\n");
        if (copy_from_user(&unlink_arg, (void*)arg, sizeof(unlink_arg)) ) {
            ret = -EFAULT;
        } else if ( strnlen(unlink_arg.name,ACH_CHAN_NAME_MAX)
                    >= ACH_CHAN_NAME_MAX ) {
            ret = -ENAMETOOLONG;
        } else {
            /* Find the device */
            struct ach_ch_device *dev;
            dev = ach_ch_device_find(unlink_arg.name);
            if (!dev) {
                ret = -ENOENT;
                goto out_unlock;
            }
            /* Free the device.  The channel
             * backing memory is ref-counted, and
             * won't be freed until all files are
             * closed.*/
            if (ach_ch_device_free(dev)) {
                ret = -ERESTARTSYS;
                goto out_unlock;
            }
            printk( KERN_INFO "ach: unlinked channel %s\n", unlink_arg.name );
        }
        break;
    }
    default:
        printk(KERN_ERR "ach: Unknown ioctl option: %d\n", cmd);
        ret = -ENOSYS;
        break;
    }

out_unlock:
    rt_mutex_unlock(&ctrl_data.lock);
    return ret;
}
Пример #8
0
static long ach_ch_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    /* TODO: Validate argument */
    int ret = 0;
    struct ach_ch_file *ch_file = (struct ach_ch_file *)file->private_data;

    KDEBUG("ach: In ach_ch_ioctl\n");

    switch (cmd) {

    case ACH_CH_SET_MODE: {
        struct achk_opt opt;
        if (copy_from_user(&opt, (void*)arg, sizeof(opt)) ) {
            ret = -EFAULT;
        } else {
            /* This is not threadsafe */
            ch_file->mode = opt;
            /* if (ch_file->mode.reltime.tv_sec != 0 */
            /*     || ch_file->mode.reltime.tv_nsec != 0) */
            /*	KDEBUG("ach: Setting wait time to %ld.%09ld\n", */
            /*	       ch_file->mode.reltime.tv_sec, */
            /*	       ch_file->mode.reltime.tv_nsec); */
            /* KDEBUG("ach: Got cmd ACH_CH_SET_MODE: \n"); */
            /* KDEBUG1("    ACH_O_WAIT=%d\n", */
            /*	ch_file->mode.mode & ACH_O_WAIT); */
            /* KDEBUG1("    ACH_O_LAST=%d\n", */
            /*	ch_file->mode.mode & ACH_O_LAST); */
            /* KDEBUG1("    ACH_O_COPY=%d\n", */
            /*	ch_file->mode.mode & ACH_O_COPY); */
            ret = 0;
            break;
        }
    }
    case ACH_CH_GET_MODE: {
        KDEBUG("ach: Got cmd ACH_CH_GET_MODE: %ld\n", arg);
        if( copy_to_user((void*)arg, &ch_file->mode, sizeof(ch_file->mode)) )
            ret = -EFAULT;
        else
            ret = 0;
        break;
    }

    case ACH_CH_GET_STATUS: {
        KDEBUG("ach: Got cmd ACH_CH_GET_STATUS\n");
        if (rt_mutex_lock_interruptible(&ch_file->shm->sync.mutex)) {
            ret = -ERESTARTSYS;
            break;
        }

        {
            struct ach_ch_status stat;
            struct ach_header *shm = ch_file->shm;
            ach_index_t *index_ar = ACH_SHM_INDEX(shm);
            size_t oldest_index = oldest_index_i(shm);
            uint64_t oldest_seq =
                index_ar[oldest_index].seq_num;

            stat.mode = ch_file->mode.options;
            stat.size = shm->len;
            stat.count = shm->index_cnt - shm->index_free;

            if (oldest_seq > ch_file->seq_num) {
                stat.new_msgs = shm->last_seq - oldest_seq;
            } else {
                stat.new_msgs =
                    shm->last_seq - ch_file->seq_num;
            }

            stat.last_seq = shm->last_seq;
            stat.last_seq_read = ch_file->seq_num;
            printk(KERN_INFO "ach: Status:\n");
            printk(KERN_INFO "ach:            mode : %02x\n",
                   stat.mode);
            printk(KERN_INFO "ach:            size : %zu\n",
                   stat.size);
            printk(KERN_INFO "ach:            count: %zu\n",
                   stat.count);
            printk(KERN_INFO "ach:            new  : %zu\n",
                   stat.new_msgs);
            printk(KERN_INFO "ach:   last_seq      : %lu\n",
                   stat.last_seq);
            printk(KERN_INFO "ach:   last_seq_read : %lu\n",
                   stat.last_seq_read);

            if (copy_to_user((void *)arg, &stat, sizeof(stat))) {
                ret = -EFAULT;
            }
        }
        rt_mutex_unlock(&ch_file->shm->sync.mutex);
    }
    case ACH_CH_FLUSH:
        KDEBUG("ach: Got cmd ACH_CH_FLUSH\n");
        ret = -get_errno( ach_flush(ch_file) );
        break;
    case ACH_CH_CANCEL: {
        unsigned int unsafe = (unsigned int)arg;
        KDEBUG("ach: Got cmd ACH_CH_CANCEL\n");
        ret = -get_errno(ach_cancel(ch_file, unsafe));
        break;
    }
    case ACH_CH_GET_OPTIONS: {
        struct ach_ch_options retval;
        retval.mode = ch_file->mode;
        retval.clock = ch_file->shm->clock;
        if( copy_to_user( (void*)arg, &retval, sizeof(retval) ) )
            ret = -EFAULT;
        else
            ret = 0;
        break;
    }
    default:
        printk(KERN_ERR "ach: Unknown ioctl option: %d\n", cmd);
        ret = -ENOSYS;
        break;
    }

    return ret;
}