/*** * rt_packet_recvmsg */ ssize_t rt_packet_recvmsg(struct rtdm_dev_context *sockctx, rtdm_user_info_t *user_info, struct msghdr *msg, int msg_flags) { struct rtsocket *sock = (struct rtsocket *)&sockctx->dev_private; size_t len = rt_iovec_len(msg->msg_iov, msg->msg_iovlen); size_t copy_len; size_t real_len; struct rtskb *skb; struct ethhdr *eth; struct sockaddr_ll *sll; int ret; nanosecs_t timeout = sock->timeout; /* non-blocking receive? */ if (testbits(msg_flags, MSG_DONTWAIT)) timeout = -1; ret = rtdm_sem_timeddown(&sock->pending_sem, timeout, NULL); if (unlikely(ret < 0)) { if ((ret != -EWOULDBLOCK) && (ret != -ETIMEDOUT)) ret = -EBADF; /* socket has been closed */ return ret; } skb = rtskb_dequeue_chain(&sock->incoming); RTNET_ASSERT(skb != NULL, return -EFAULT;);
/*** * rt_packet_recvmsg */ static ssize_t rt_packet_recvmsg(struct rtdm_fd *fd, struct msghdr *msg, int msg_flags) { struct rtsocket *sock = rtdm_fd_to_private(fd); size_t len = rt_iovec_len(msg->msg_iov, msg->msg_iovlen); size_t copy_len; size_t real_len; struct rtskb *rtskb; struct sockaddr_ll *sll; int ret; nanosecs_rel_t timeout = sock->timeout; /* non-blocking receive? */ if (msg_flags & MSG_DONTWAIT) timeout = -1; ret = rtdm_sem_timeddown(&sock->pending_sem, timeout, NULL); if (unlikely(ret < 0)) switch (ret) { case -EWOULDBLOCK: case -ETIMEDOUT: case -EINTR: return ret; default: return -EBADF; /* socket has been closed */ } rtskb = rtskb_dequeue_chain(&sock->incoming); RTNET_ASSERT(rtskb != NULL, return -EFAULT;);
void task2(void *cookie) { long i, max; nanosecs_abs_t t, dt; rt_printk("TESTING TIMING OUT TIMEDDOWN ..."); for (max = i = 0; i < LOOPS; i++) { t = rtdm_clock_read(); if (rtdm_sem_timeddown(&sem2, DELAY, NULL) == -ETIMEDOUT) { dt = rtdm_clock_read() - t - DELAY; if (dt > max) { max = dt; } } else { break; } } if (i == LOOPS) { rt_printk(" OK [%lu (ns)].\n", max); } else { rt_printk(" NOT OK [MAXLAT %lu (ns)].\n", max); } rt_printk("TESTING FAILING TRY DOWN ..."); for (i = 0; i < LOOPS; i++) { if (rtdm_sem_timeddown(&sem2, RTDM_TIMEOUT_NONE, NULL) != -EWOULDBLOCK) { break; } } if (i == LOOPS) { rt_printk(" OK.\n"); } else { rt_printk(" NOT OK.\n", max); } rt_printk("TESTING SUCCEEDING TRY DOWN ..."); rtdm_sem_up(&sem2); for (i = 0; i < LOOPS; i++) { if (!rtdm_sem_timeddown(&sem2, RTDM_TIMEOUT_NONE, NULL)) { rtdm_sem_up(&sem2); } else { break; } } if (i == LOOPS) { rt_printk(" OK.\n"); } else { rt_printk(" NOT OK.\n", max); } rt_printk("TESTING DOWN/UP ..."); rtdm_sem_down(&sem2); for (i = 0; i < LOOPS; i++) { rtdm_sem_up(&sem1); if (rtdm_sem_down(&sem2)) { break; } } if (i == LOOPS) { rt_printk(" OK.\n"); } else { rt_printk(" NOT OK.\n", max); } rt_printk("TESTING NOT TIMING OUT TIMEDDOWN ..."); for (i = 0; i < LOOPS; i++) { rtdm_sem_up(&sem1); if (rtdm_sem_timeddown(&sem2, DELAY, NULL)) { break; } } if (i == LOOPS) { rt_printk(" OK.\n"); } else { rt_printk(" NOT OK.\n", max); } }
static int rtdmtest_ioctl(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg) { struct rtdmtest_context *ctx; struct rttst_rtdmtest_config config_buf, *config; rtdm_toseq_t toseq_local, *toseq = NULL; int i, err = 0; ctx = (struct rtdmtest_context *)context->dev_private; switch (request) { case RTTST_RTIOC_RTDMTEST_SEM_TIMEDDOWN: case RTTST_RTIOC_RTDMTEST_EVENT_TIMEDWAIT: case RTTST_RTIOC_RTDMTEST_MUTEX_TIMEDTEST: case RTTST_RTIOC_RTDMTEST_MUTEX_TEST: config = arg; if (user_info) { if (rtdm_safe_copy_from_user (user_info, &config_buf, arg, sizeof(struct rttst_rtdmtest_config)) < 0) return -EFAULT; config = &config_buf; } if (!config->seqcount) config->seqcount = 1; if (config->timeout && config->seqcount > 1) { toseq = &toseq_local; rtdm_toseq_init(toseq, config->timeout); } switch(request) { case RTTST_RTIOC_RTDMTEST_SEM_TIMEDDOWN: for (i = 0; i < config->seqcount; i++) { err = rtdm_sem_timeddown(&ctx->sem, config->timeout, toseq); if (err) break; } break; case RTTST_RTIOC_RTDMTEST_EVENT_TIMEDWAIT: for (i = 0; i < config->seqcount; i++) { err = rtdm_event_timedwait(&ctx->event, config->timeout, toseq); if (err) break; } break; case RTTST_RTIOC_RTDMTEST_MUTEX_TIMEDTEST: for (i = 0; i < config->seqcount; i++) { err = rtdm_mutex_timedlock(&ctx->mutex, config->timeout, toseq); if (err) break; if (config->delay_jiffies) { __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(config->delay_jiffies); } rtdm_lock_count++; rtdm_mutex_unlock(&ctx->mutex); } break; case RTTST_RTIOC_RTDMTEST_MUTEX_TEST: for (i = 0; i < config->seqcount; i++) { if ((err = rtdm_mutex_lock(&ctx->mutex))) break; rtdm_lock_count++; rtdm_mutex_unlock(&ctx->mutex); } break; } break; case RTTST_RTIOC_RTDMTEST_SEM_DOWN: err = rtdm_sem_down(&ctx->sem); break; case RTTST_RTIOC_RTDMTEST_SEM_UP: rtdm_sem_up(&ctx->sem); break; case RTTST_RTIOC_RTDMTEST_SEM_DESTROY: rtdm_sem_destroy(&ctx->sem); break; case RTTST_RTIOC_RTDMTEST_EVENT_WAIT: err = rtdm_event_wait(&ctx->event); break; case RTTST_RTIOC_RTDMTEST_EVENT_SIGNAL: rtdm_event_signal(&ctx->event); break; case RTTST_RTIOC_RTDMTEST_EVENT_DESTROY: rtdm_event_destroy(&ctx->event); break; case RTTST_RTIOC_RTDMTEST_MUTEX_DESTROY: rtdm_mutex_destroy(&ctx->mutex); break; case RTTST_RTIOC_RTDMTEST_MUTEX_GETSTAT: printk("RTTST_RTIOC_RTDMTEST_MUTEX_GETSTAT\n"); if (user_info) config = &config_buf; else config = arg; config->seqcount = rtdm_lock_count; if (user_info) { if (rtdm_safe_copy_to_user (user_info, arg, &config_buf, sizeof(struct rttst_rtdmtest_config)) < 0) return -EFAULT; } break; case RTTST_RTIOC_RTDMTEST_NRTSIG_PEND: rtdm_nrtsig_pend(&ctx->nrtsig); break; case RTTST_RTIOC_RTDMTEST_TASK_CREATE: case RTTST_RTIOC_RTDMTEST_TASK_SET_PRIO: config = arg; if (user_info) { if (rtdm_safe_copy_from_user (user_info, &config_buf, arg, sizeof(struct rttst_rtdmtest_config)) < 0) return -EFAULT; config = &config_buf; } if (request == RTTST_RTIOC_RTDMTEST_TASK_CREATE) { task_period = config->timeout; rtdm_task_init(&task, "RTDMTEST", rtdmtest_task, (void *)config, config->priority, 0); } else { rtdm_task_set_priority(&task, config->priority); } break; case RTTST_RTIOC_RTDMTEST_TASK_DESTROY: rtdm_task_destroy(&task); rtdm_task_join_nrt(&task, 100); break; default: printk("request=%d\n", request); err = -ENOTTY; } return err; }