Ejemplo n.º 1
0
Archivo: ach.c Proyecto: petevieira/ach
/** Copies frame pointed to by index entry at index_offset.

    \pre hold read lock on the channel

    \pre on success, buf holds the frame seq_num and next_index fields
    are incremented. The variable pointed to by size_written holds the
    number of bytes written to buf (0 on failure).
*/
static enum ach_status
ach_get_from_offset( ach_channel_t *chan, size_t index_offset,
                     char *buf, size_t size, size_t *frame_size ) {
    ach_header_t *shm = chan->shm;
    assert( index_offset < shm->index_cnt );
    ach_index_t *idx = ACH_SHM_INDEX(shm) + index_offset;
    /* assert( idx->size ); */
    assert( idx->seq_num );
    assert( idx->offset < shm->data_size );
    /* check idx */
    if( chan->seq_num > idx->seq_num ) {
        fprintf(stderr,
                "ach bug: chan->seq_num (%"PRIu64") > idx->seq_num (%"PRIu64")\n"
                "ach bug: index offset: %"PRIuPTR"\n",
                chan->seq_num, idx->seq_num,
                index_offset );
        return ACH_BUG;
    }

    if(  idx->size > size ) {
        /* buffer overflow */
        *frame_size = idx->size;
        return ACH_OVERFLOW;
    } else {
        /* good to copy */
        uint8_t *data_buf = ACH_SHM_DATA(shm);
        if( idx->offset + idx->size < shm->data_size ) {
            /* simple memcpy */
            memcpy( (uint8_t*)buf, data_buf + idx->offset, idx->size );
        }else {
            /* wraparound memcpy */
            size_t end_cnt = shm->data_size - idx->offset;
            memcpy( (uint8_t*)buf, data_buf + idx->offset, end_cnt );
            memcpy( (uint8_t*)buf + end_cnt, data_buf, idx->size - end_cnt );
        }
        *frame_size = idx->size;
        chan->seq_num = idx->seq_num;
        chan->next_index = (index_offset + 1) % shm->index_cnt;
        return ACH_OK;
    }
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
Archivo: ach.c Proyecto: petevieira/ach
            memcpy( (uint8_t*)buf + end_cnt, data_buf, idx->size - end_cnt );
        }
        *frame_size = idx->size;
        chan->seq_num = idx->seq_num;
        chan->next_index = (index_offset + 1) % shm->index_cnt;
        return ACH_OK;
    }
}

enum ach_status
ach_get( ach_channel_t *chan, void *buf, size_t size,
         size_t *frame_size,
         const struct timespec *ACH_RESTRICT abstime,
         int options ) {
    ach_header_t *shm = chan->shm;
    ach_index_t *index_ar = ACH_SHM_INDEX(shm);

    /* Check guard bytes */
    {
        enum ach_status r = check_guards(shm);
        if( ACH_OK != r ) return r;
    }

    const bool o_wait = options & ACH_O_WAIT;
    const bool o_last = options & ACH_O_LAST;
    const bool o_copy = options & ACH_O_COPY;

    /* take read lock */
    if( o_wait ) {
        enum ach_status r;
        if( ACH_OK != (r = rdlock_wait( shm, chan, abstime ) ) ) {