The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/vmware/vmci/vmci_qpair.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2018 VMware, Inc.
    3  *
    4  * SPDX-License-Identifier: (BSD-2-Clause OR GPL-2.0)
    5  */
    6 
    7 /* This file implements Queue accessor methods. */
    8 
    9 /*
   10  * vmci_qpair is an interface that hides the queue pair internals. Rather than
   11  * access each queue in a pair directly, operations are performed on the queue
   12  * as a whole. This is simpler and less error-prone, and allows for future
   13  * queue pair features to be added under the hood with no change to the client
   14  * code.
   15  */
   16 
   17 #include <sys/cdefs.h>
   18 __FBSDID("$FreeBSD$");
   19 
   20 #include "vmci_kernel_api.h"
   21 #include "vmci_kernel_defs.h"
   22 #include "vmci_kernel_if.h"
   23 #include "vmci_queue.h"
   24 #include "vmci_queue_pair.h"
   25 
   26 /* This structure is opaque to the clients. */
   27 struct vmci_qpair {
   28         struct vmci_handle      handle;
   29         struct vmci_queue       *produce_q;
   30         struct vmci_queue       *consume_q;
   31         uint64_t                produce_q_size;
   32         uint64_t                consume_q_size;
   33         vmci_id                 peer;
   34         uint32_t                flags;
   35         vmci_privilege_flags    priv_flags;
   36         uint32_t                blocked;
   37         vmci_event              event;
   38 };
   39 
   40 static void     vmci_qpair_get_queue_headers(const struct vmci_qpair *qpair,
   41                     struct vmci_queue_header **produce_q_header,
   42                     struct vmci_queue_header **consume_q_header);
   43 
   44 /*
   45  *------------------------------------------------------------------------------
   46  *
   47  * vmci_queue_add_producer_tail --
   48  *
   49  *     Helper routine to increment the Producer Tail.
   50  *
   51  * Results:
   52  *     VMCI_ERROR_NOT_FOUND if the vmm_world registered with the queue cannot
   53  *     be found. Otherwise VMCI_SUCCESS.
   54  *
   55  * Side effects:
   56  *     None.
   57  *
   58  *------------------------------------------------------------------------------
   59  */
   60 
   61 static inline int
   62 vmci_queue_add_producer_tail(struct vmci_queue *queue,
   63     size_t add, uint64_t queue_size)
   64 {
   65 
   66         vmci_queue_header_add_producer_tail(queue->q_header, add, queue_size);
   67         return (VMCI_SUCCESS);
   68 }
   69 
   70 /*
   71  *------------------------------------------------------------------------------
   72  *
   73  * vmci_queue_add_consumer_head --
   74  *
   75  *     Helper routine to increment the Consumer Head.
   76  *
   77  * Results:
   78  *     VMCI_ERROR_NOT_FOUND if the vmm_world registered with the queue cannot
   79  *     be found. Otherwise VMCI_SUCCESS.
   80  *
   81  * Side effects:
   82  *     None.
   83  *
   84  *------------------------------------------------------------------------------
   85  */
   86 
   87 static inline int
   88 vmci_queue_add_consumer_head(struct vmci_queue *queue,
   89     size_t add, uint64_t queue_size)
   90 {
   91 
   92         vmci_queue_header_add_consumer_head(queue->q_header, add, queue_size);
   93         return (VMCI_SUCCESS);
   94 }
   95 
   96 /*
   97  *------------------------------------------------------------------------------
   98  *
   99  * vmci_qpair_get_queue_headers --
  100  *
  101  *     Helper routine that will retrieve the produce and consume headers of a
  102  *     given queue pair.
  103  *
  104  * Results:
  105  *     VMCI_SUCCESS if either current or saved queue headers are found.
  106  *     Appropriate error code otherwise.
  107  *
  108  * Side effects:
  109  *     None.
  110  *
  111  *------------------------------------------------------------------------------
  112  */
  113 
  114 static void
  115 vmci_qpair_get_queue_headers(const struct vmci_qpair *qpair,
  116     struct vmci_queue_header **produce_q_header,
  117     struct vmci_queue_header **consume_q_header)
  118 {
  119 
  120         ASSERT((qpair->produce_q != NULL) && (qpair->consume_q != NULL));
  121         *produce_q_header = qpair->produce_q->q_header;
  122         *consume_q_header = qpair->consume_q->q_header;
  123 }
  124 
  125 /*
  126  *------------------------------------------------------------------------------
  127  *
  128  * vmci_qpair_alloc --
  129  *
  130  *     This is the client interface for allocating the memory for a vmci_qpair
  131  *     structure and then attaching to the underlying queue. If an error occurs
  132  *     allocating the memory for the vmci_qpair structure, no attempt is made to
  133  *     attach. If an error occurs attaching, then there's the vmci_qpair
  134  *     structure is freed.
  135  *
  136  * Results:
  137  *     An err, if < 0.
  138  *
  139  * Side effects:
  140  *     None.
  141  *
  142  *------------------------------------------------------------------------------
  143  */
  144 
  145 int
  146 vmci_qpair_alloc(struct vmci_qpair **qpair, struct vmci_handle *handle,
  147     uint64_t produce_q_size, uint64_t consume_q_size, vmci_id peer,
  148     uint32_t flags, vmci_privilege_flags priv_flags)
  149 {
  150         struct vmci_qpair *my_qpair;
  151         int retval;
  152 
  153         /*
  154          * Restrict the size of a queuepair. Though the device enforces a limit
  155          * on the total amount of memory that can be allocated to queuepairs for
  156          * a guest, we avoid unnecessarily allocating a lot of memory. Also, we
  157          * try to allocate this memory before we make the queuepair allocation
  158          * hypercall.
  159          *
  160          * (Note that this doesn't prevent all cases; a user with only this much
  161          * physical memory could still get into trouble.) The error used by the
  162          * device is NO_RESOURCES, so use that here too.
  163          */
  164 
  165         if (produce_q_size + consume_q_size <
  166             MAX(produce_q_size, consume_q_size) ||
  167             produce_q_size + consume_q_size > VMCI_MAX_GUEST_QP_MEMORY)
  168                 return (VMCI_ERROR_NO_RESOURCES);
  169 
  170         if (flags & VMCI_QPFLAG_NONBLOCK)
  171                 return (VMCI_ERROR_INVALID_ARGS);
  172 
  173         my_qpair = vmci_alloc_kernel_mem(sizeof(*my_qpair), VMCI_MEMORY_NORMAL);
  174         if (!my_qpair)
  175                 return (VMCI_ERROR_NO_MEM);
  176 
  177         my_qpair->produce_q_size = produce_q_size;
  178         my_qpair->consume_q_size = consume_q_size;
  179         my_qpair->peer = peer;
  180         my_qpair->flags = flags;
  181         my_qpair->priv_flags = priv_flags;
  182 
  183         retval = vmci_queue_pair_alloc(handle, &my_qpair->produce_q,
  184             my_qpair->produce_q_size, &my_qpair->consume_q,
  185             my_qpair->consume_q_size, my_qpair->peer, my_qpair->flags,
  186             my_qpair->priv_flags);
  187 
  188         if (retval < VMCI_SUCCESS) {
  189                 vmci_free_kernel_mem(my_qpair, sizeof(*my_qpair));
  190                 return (retval);
  191         }
  192 
  193         *qpair = my_qpair;
  194         my_qpair->handle = *handle;
  195 
  196         return (retval);
  197 }
  198 
  199 /*
  200  *------------------------------------------------------------------------------
  201  *
  202  * vmci_qpair_detach --
  203  *
  204  *     This is the client interface for detaching from a vmci_qpair. Note that
  205  *     this routine will free the memory allocated for the vmci_qpair structure,
  206  *     too.
  207  *
  208  * Results:
  209  *     An error, if < 0.
  210  *
  211  * Side effects:
  212  *     Will clear the caller's pointer to the vmci_qpair structure.
  213  *
  214  *------------------------------------------------------------------------------
  215  */
  216 
  217 int
  218 vmci_qpair_detach(struct vmci_qpair **qpair)
  219 {
  220         struct vmci_qpair *old_qpair;
  221         int result;
  222 
  223         if (!qpair || !(*qpair))
  224                 return (VMCI_ERROR_INVALID_ARGS);
  225 
  226         old_qpair = *qpair;
  227         result = vmci_queue_pair_detach(old_qpair->handle);
  228 
  229         /*
  230          * The guest can fail to detach for a number of reasons, and if it does
  231          * so, it will cleanup the entry (if there is one). We need to release
  232          * the qpair struct here; there isn't much the caller can do, and we
  233          * don't want to leak.
  234          */
  235 
  236         if (old_qpair->flags & VMCI_QPFLAG_LOCAL)
  237                 vmci_destroy_event(&old_qpair->event);
  238 
  239         vmci_free_kernel_mem(old_qpair, sizeof(*old_qpair));
  240         *qpair = NULL;
  241 
  242         return (result);
  243 }
  244 
  245 /*
  246  *------------------------------------------------------------------------------
  247  *
  248  * vmci_qpair_get_produce_indexes --
  249  *
  250  *     This is the client interface for getting the current indexes of the
  251  *     qpair from the point of the view of the caller as the producer.
  252  *
  253  * Results:
  254  *     err, if < 0
  255  *     Success otherwise.
  256  *
  257  * Side effects:
  258  *     None.
  259  *
  260  *------------------------------------------------------------------------------
  261  */
  262 
  263 int
  264 vmci_qpair_get_produce_indexes(const struct vmci_qpair *qpair,
  265     uint64_t *producer_tail, uint64_t *consumer_head)
  266 {
  267         struct vmci_queue_header *consume_q_header;
  268         struct vmci_queue_header *produce_q_header;
  269 
  270         if (!qpair)
  271                 return (VMCI_ERROR_INVALID_ARGS);
  272 
  273         vmci_qpair_get_queue_headers(qpair, &produce_q_header,
  274             &consume_q_header);
  275         vmci_queue_header_get_pointers(produce_q_header, consume_q_header,
  276             producer_tail, consumer_head);
  277 
  278         if ((producer_tail && *producer_tail >= qpair->produce_q_size) ||
  279             (consumer_head && *consumer_head >= qpair->produce_q_size))
  280                 return (VMCI_ERROR_INVALID_SIZE);
  281 
  282         return (VMCI_SUCCESS);
  283 }
  284 
  285 /*
  286  *------------------------------------------------------------------------------
  287  *
  288  * vmci_qpair_get_consume_indexes --
  289  *
  290  *     This is the client interface for getting the current indexes of the
  291  *     QPair from the point of the view of the caller as the consumer.
  292  *
  293  * Results:
  294  *     err, if < 0
  295  *     Success otherwise.
  296  *
  297  * Side effects:
  298  *     None.
  299  *
  300  *------------------------------------------------------------------------------
  301  */
  302 
  303 int
  304 vmci_qpair_get_consume_indexes(const struct vmci_qpair *qpair,
  305     uint64_t *consumer_tail, uint64_t *producer_head)
  306 {
  307         struct vmci_queue_header *consume_q_header;
  308         struct vmci_queue_header *produce_q_header;
  309 
  310         if (!qpair)
  311                 return (VMCI_ERROR_INVALID_ARGS);
  312 
  313         vmci_qpair_get_queue_headers(qpair, &produce_q_header,
  314             &consume_q_header);
  315         vmci_queue_header_get_pointers(consume_q_header, produce_q_header,
  316             consumer_tail, producer_head);
  317 
  318         if ((consumer_tail && *consumer_tail >= qpair->consume_q_size) ||
  319             (producer_head && *producer_head >= qpair->consume_q_size))
  320                 return (VMCI_ERROR_INVALID_SIZE);
  321 
  322         return (VMCI_SUCCESS);
  323 }
  324 
  325 /*
  326  *------------------------------------------------------------------------------
  327  *
  328  * vmci_qpair_produce_free_space --
  329  *
  330  *     This is the client interface for getting the amount of free space in the
  331  *     QPair from the point of the view of the caller as the producer which is
  332  *     the common case.
  333  *
  334  * Results:
  335  *     Err, if < 0.
  336  *     Full queue if = 0.
  337  *     Number of available bytes into which data can be enqueued if > 0.
  338  *
  339  * Side effects:
  340  *     None.
  341  *
  342  *------------------------------------------------------------------------------
  343  */
  344 
  345 int64_t
  346 vmci_qpair_produce_free_space(const struct vmci_qpair *qpair)
  347 {
  348         struct vmci_queue_header *consume_q_header;
  349         struct vmci_queue_header *produce_q_header;
  350         int64_t result;
  351 
  352         if (!qpair)
  353                 return (VMCI_ERROR_INVALID_ARGS);
  354 
  355         vmci_qpair_get_queue_headers(qpair, &produce_q_header,
  356             &consume_q_header);
  357         result = vmci_queue_header_free_space(produce_q_header, consume_q_header,
  358             qpair->produce_q_size);
  359 
  360         return (result);
  361 }
  362 
  363 /*
  364  *------------------------------------------------------------------------------
  365  *
  366  * vmci_qpair_consume_free_space --
  367  *
  368  *     This is the client interface for getting the amount of free space in the
  369  *     QPair from the point of the view of the caller as the consumer which is
  370  *     not the common case (see vmci_qpair_Produce_free_space(), above).
  371  *
  372  * Results:
  373  *     Err, if < 0.
  374  *     Full queue if = 0.
  375  *     Number of available bytes into which data can be enqueued if > 0.
  376  *
  377  * Side effects:
  378  *     None.
  379  *
  380  *------------------------------------------------------------------------------
  381  */
  382 
  383 int64_t
  384 vmci_qpair_consume_free_space(const struct vmci_qpair *qpair)
  385 {
  386         struct vmci_queue_header *consume_q_header;
  387         struct vmci_queue_header *produce_q_header;
  388         int64_t result;
  389 
  390         if (!qpair)
  391                 return (VMCI_ERROR_INVALID_ARGS);
  392 
  393         vmci_qpair_get_queue_headers(qpair, &produce_q_header,
  394             &consume_q_header);
  395         result = vmci_queue_header_free_space(consume_q_header, produce_q_header,
  396             qpair->consume_q_size);
  397 
  398         return (result);
  399 }
  400 
  401 /*
  402  *------------------------------------------------------------------------------
  403  *
  404  * vmci_qpair_produce_buf_ready --
  405  *
  406  *     This is the client interface for getting the amount of enqueued data in
  407  *     the QPair from the point of the view of the caller as the producer which
  408  *     is not the common case (see vmci_qpair_Consume_buf_ready(), above).
  409  *
  410  * Results:
  411  *     Err, if < 0.
  412  *     Empty queue if = 0.
  413  *     Number of bytes ready to be dequeued if > 0.
  414  *
  415  * Side effects:
  416  *     None.
  417  *
  418  *------------------------------------------------------------------------------
  419  */
  420 
  421 int64_t
  422 vmci_qpair_produce_buf_ready(const struct vmci_qpair *qpair)
  423 {
  424         struct vmci_queue_header *consume_q_header;
  425         struct vmci_queue_header *produce_q_header;
  426         int64_t result;
  427 
  428         if (!qpair)
  429                 return (VMCI_ERROR_INVALID_ARGS);
  430 
  431         vmci_qpair_get_queue_headers(qpair, &produce_q_header,
  432             &consume_q_header);
  433         result = vmci_queue_header_buf_ready(produce_q_header, consume_q_header,
  434             qpair->produce_q_size);
  435 
  436         return (result);
  437 }
  438 
  439 /*
  440  *------------------------------------------------------------------------------
  441  *
  442  * vmci_qpair_consume_buf_ready --
  443  *
  444  *     This is the client interface for getting the amount of enqueued data in
  445  *     the QPair from the point of the view of the caller as the consumer which
  446  *     is the normal case.
  447  *
  448  * Results:
  449  *     Err, if < 0.
  450  *     Empty queue if = 0.
  451  *     Number of bytes ready to be dequeued if > 0.
  452  *
  453  * Side effects:
  454  *     None.
  455  *
  456  *------------------------------------------------------------------------------
  457  */
  458 
  459 int64_t
  460 vmci_qpair_consume_buf_ready(const struct vmci_qpair *qpair)
  461 {
  462         struct vmci_queue_header *consume_q_header;
  463         struct vmci_queue_header *produce_q_header;
  464         int64_t result;
  465 
  466         if (!qpair)
  467                 return (VMCI_ERROR_INVALID_ARGS);
  468 
  469         vmci_qpair_get_queue_headers(qpair, &produce_q_header,
  470             &consume_q_header);
  471         result = vmci_queue_header_buf_ready(consume_q_header, produce_q_header,
  472             qpair->consume_q_size);
  473 
  474         return (result);
  475 }
  476 
  477 /*
  478  *------------------------------------------------------------------------------
  479  *
  480  * enqueue --
  481  *
  482  *     Enqueues a given buffer to the produce queue using the provided function.
  483  *     As many bytes as possible (space available in the queue) are enqueued.
  484  *
  485  * Results:
  486  *     VMCI_ERROR_QUEUEPAIR_NOSPACE if no space was available to enqueue data.
  487  *     VMCI_ERROR_INVALID_SIZE, if any queue pointer is outside the queue
  488  *     (as defined by the queue size).
  489  *     VMCI_ERROR_INVALID_ARGS, if an error occurred when accessing the buffer.
  490  *     VMCI_ERROR_QUEUEPAIR_NOTATTACHED, if the queue pair pages aren't
  491  *     available.
  492  *     Otherwise, the number of bytes written to the queue is returned.
  493  *
  494  * Side effects:
  495  *     Updates the tail pointer of the produce queue.
  496  *
  497  *------------------------------------------------------------------------------
  498  */
  499 
  500 static ssize_t
  501 enqueue(struct vmci_queue *produce_q, struct vmci_queue *consume_q,
  502     const uint64_t produce_q_size, const void *buf, size_t buf_size,
  503     int buf_type, vmci_memcpy_to_queue_func memcpy_to_queue, bool can_block)
  504 {
  505         ssize_t result;
  506         size_t written;
  507         int64_t free_space;
  508         uint64_t tail;
  509 
  510         ASSERT((produce_q != NULL) && (consume_q != NULL));
  511 
  512         free_space = vmci_queue_header_free_space(produce_q->q_header,
  513             consume_q->q_header,
  514             produce_q_size);
  515         if (free_space == 0)
  516                 return (VMCI_ERROR_QUEUEPAIR_NOSPACE);
  517 
  518         if (free_space < VMCI_SUCCESS)
  519                 return ((ssize_t)free_space);
  520 
  521         written = (size_t)(free_space > buf_size ? buf_size : free_space);
  522         tail = vmci_queue_header_producer_tail(produce_q->q_header);
  523         if (LIKELY(tail + written < produce_q_size))
  524                 result = memcpy_to_queue(produce_q, tail, buf, 0, written,
  525                     buf_type, can_block);
  526         else {
  527                 /* Tail pointer wraps around. */
  528 
  529                 const size_t tmp = (size_t)(produce_q_size - tail);
  530 
  531                 result = memcpy_to_queue(produce_q, tail, buf, 0, tmp, buf_type,
  532                     can_block);
  533                 if (result >= VMCI_SUCCESS)
  534                         result = memcpy_to_queue(produce_q, 0, buf, tmp,
  535                             written - tmp, buf_type, can_block);
  536         }
  537 
  538         if (result < VMCI_SUCCESS)
  539                 return (result);
  540 
  541         result = vmci_queue_add_producer_tail(produce_q, written,
  542             produce_q_size);
  543         if (result < VMCI_SUCCESS)
  544                 return (result);
  545         return (written);
  546 }
  547 
  548 /*
  549  *------------------------------------------------------------------------------
  550  *
  551  * dequeue --
  552  *
  553  *     Dequeues data (if available) from the given consume queue. Writes data
  554  *     to the user provided buffer using the provided function.
  555  *
  556  * Results:
  557  *     VMCI_ERROR_QUEUEPAIR_NODATA if no data was available to dequeue.
  558  *     VMCI_ERROR_INVALID_SIZE, if any queue pointer is outside the queue
  559  *     (as defined by the queue size).
  560  *     VMCI_ERROR_INVALID_ARGS, if an error occurred when accessing the buffer.
  561  *     VMCI_ERROR_NOT_FOUND, if the vmm_world registered with the queue pair
  562  *     cannot be found.
  563  *     Otherwise the number of bytes dequeued is returned.
  564  *
  565  * Side effects:
  566  *     Updates the head pointer of the consume queue.
  567  *
  568  *------------------------------------------------------------------------------
  569  */
  570 
  571 static ssize_t
  572 dequeue(struct vmci_queue *produce_q,
  573     struct vmci_queue *consume_q, const uint64_t consume_q_size, void *buf,
  574     size_t buf_size, int buf_type,
  575     vmci_memcpy_from_queue_func memcpy_from_queue, bool update_consumer,
  576     bool can_block)
  577 {
  578         ssize_t result;
  579         size_t read;
  580         int64_t buf_ready;
  581         uint64_t head;
  582 
  583         ASSERT((produce_q != NULL) && (consume_q != NULL));
  584 
  585         buf_ready = vmci_queue_header_buf_ready(consume_q->q_header,
  586             produce_q->q_header, consume_q_size);
  587         if (buf_ready == 0)
  588                 return (VMCI_ERROR_QUEUEPAIR_NODATA);
  589         if (buf_ready < VMCI_SUCCESS)
  590                 return ((ssize_t)buf_ready);
  591 
  592         read = (size_t)(buf_ready > buf_size ? buf_size : buf_ready);
  593         head = vmci_queue_header_consumer_head(produce_q->q_header);
  594         if (LIKELY(head + read < consume_q_size))
  595                 result = memcpy_from_queue(buf, 0, consume_q, head, read,
  596                     buf_type, can_block);
  597         else {
  598                 /* Head pointer wraps around. */
  599 
  600                 const size_t tmp = (size_t)(consume_q_size - head);
  601 
  602                 result = memcpy_from_queue(buf, 0, consume_q, head, tmp,
  603                     buf_type, can_block);
  604                 if (result >= VMCI_SUCCESS)
  605                         result = memcpy_from_queue(buf, tmp, consume_q, 0,
  606                             read - tmp, buf_type, can_block);
  607         }
  608 
  609         if (result < VMCI_SUCCESS)
  610                 return (result);
  611 
  612         if (update_consumer) {
  613                 result = vmci_queue_add_consumer_head(produce_q, read,
  614                     consume_q_size);
  615                 if (result < VMCI_SUCCESS)
  616                         return (result);
  617         }
  618 
  619         return (read);
  620 }
  621 
  622 /*
  623  *------------------------------------------------------------------------------
  624  *
  625  * vmci_qpair_enqueue --
  626  *
  627  *     This is the client interface for enqueueing data into the queue.
  628  *
  629  * Results:
  630  *     Err, if < 0.
  631  *     Number of bytes enqueued if >= 0.
  632  *
  633  * Side effects:
  634  *     None.
  635  *
  636  *------------------------------------------------------------------------------
  637  */
  638 
  639 ssize_t
  640 vmci_qpair_enqueue(struct vmci_qpair *qpair, const void *buf, size_t buf_size,
  641     int buf_type)
  642 {
  643         ssize_t result;
  644 
  645         if (!qpair || !buf)
  646                 return (VMCI_ERROR_INVALID_ARGS);
  647 
  648         result = enqueue(qpair->produce_q, qpair->consume_q,
  649             qpair->produce_q_size, buf, buf_size, buf_type,
  650             qpair->flags & VMCI_QPFLAG_LOCAL?
  651             vmci_memcpy_to_queue_local : vmci_memcpy_to_queue,
  652             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
  653 
  654         return (result);
  655 }
  656 
  657 /*
  658  *------------------------------------------------------------------------------
  659  *
  660  * vmci_qpair_dequeue --
  661  *
  662  *     This is the client interface for dequeueing data from the queue.
  663  *
  664  * Results:
  665  *     Err, if < 0.
  666  *     Number of bytes dequeued if >= 0.
  667  *
  668  * Side effects:
  669  *     None.
  670  *
  671  *------------------------------------------------------------------------------
  672  */
  673 
  674 ssize_t
  675 vmci_qpair_dequeue(struct vmci_qpair *qpair, void *buf, size_t buf_size,
  676     int buf_type)
  677 {
  678         ssize_t result;
  679 
  680         if (!qpair || !buf)
  681                 return (VMCI_ERROR_INVALID_ARGS);
  682 
  683         result = dequeue(qpair->produce_q, qpair->consume_q,
  684             qpair->consume_q_size, buf, buf_size, buf_type,
  685             qpair->flags & VMCI_QPFLAG_LOCAL?
  686             vmci_memcpy_from_queue_local : vmci_memcpy_from_queue, true,
  687             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
  688 
  689         return (result);
  690 }
  691 
  692 /*
  693  *------------------------------------------------------------------------------
  694  *
  695  * vmci_qpair_peek --
  696  *
  697  *     This is the client interface for peeking into a queue.  (I.e., copy
  698  *     data from the queue without updating the head pointer.)
  699  *
  700  * Results:
  701  *     Err, if < 0.
  702  *     Number of bytes peeked, if >= 0.
  703  *
  704  * Side effects:
  705  *     None.
  706  *
  707  *------------------------------------------------------------------------------
  708  */
  709 
  710 ssize_t
  711 vmci_qpair_peek(struct vmci_qpair *qpair, void *buf, size_t buf_size,
  712     int buf_type)
  713 {
  714         ssize_t result;
  715 
  716         if (!qpair || !buf)
  717                 return (VMCI_ERROR_INVALID_ARGS);
  718 
  719         result = dequeue(qpair->produce_q, qpair->consume_q,
  720             qpair->consume_q_size, buf, buf_size, buf_type,
  721             qpair->flags & VMCI_QPFLAG_LOCAL?
  722             vmci_memcpy_from_queue_local : vmci_memcpy_from_queue, false,
  723             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
  724 
  725         return (result);
  726 }
  727 
  728 /*
  729  *------------------------------------------------------------------------------
  730  *
  731  * vmci_qpair_enquev --
  732  *
  733  *     This is the client interface for enqueueing data into the queue.
  734  *
  735  * Results:
  736  *     Err, if < 0.
  737  *     Number of bytes enqueued if >= 0.
  738  *
  739  * Side effects:
  740  *     None.
  741  *
  742  *------------------------------------------------------------------------------
  743  */
  744 
  745 ssize_t
  746 vmci_qpair_enquev(struct vmci_qpair *qpair, void *iov, size_t iov_size,
  747     int buf_type)
  748 {
  749         ssize_t result;
  750 
  751         if (!qpair || !iov)
  752                 return (VMCI_ERROR_INVALID_ARGS);
  753 
  754         result = enqueue(qpair->produce_q, qpair->consume_q,
  755             qpair->produce_q_size, iov, iov_size, buf_type,
  756             qpair->flags & VMCI_QPFLAG_LOCAL?
  757             vmci_memcpy_to_queue_v_local : vmci_memcpy_to_queue_v,
  758             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
  759 
  760         return (result);
  761 }
  762 
  763 /*
  764  *------------------------------------------------------------------------------
  765  *
  766  * vmci_qpair_dequev --
  767  *
  768  *     This is the client interface for dequeueing data from the queue.
  769  *
  770  * Results:
  771  *     Err, if < 0.
  772  *     Number of bytes dequeued if >= 0.
  773  *
  774  * Side effects:
  775  *     None.
  776  *
  777  *------------------------------------------------------------------------------
  778  */
  779 
  780 ssize_t
  781 vmci_qpair_dequev(struct vmci_qpair *qpair, void *iov, size_t iov_size,
  782     int buf_type)
  783 {
  784         ssize_t result;
  785 
  786         if (!qpair || !iov)
  787                 return (VMCI_ERROR_INVALID_ARGS);
  788 
  789         result = dequeue(qpair->produce_q, qpair->consume_q,
  790             qpair->consume_q_size, iov, iov_size, buf_type,
  791             qpair->flags & VMCI_QPFLAG_LOCAL?
  792             vmci_memcpy_from_queue_v_local : vmci_memcpy_from_queue_v, true,
  793             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
  794 
  795         return (result);
  796 }
  797 
  798 /*
  799  *------------------------------------------------------------------------------
  800  *
  801  * vmci_qpair_peekv --
  802  *
  803  *     This is the client interface for peeking into a queue.  (I.e., copy
  804  *     data from the queue without updating the head pointer.)
  805  *
  806  * Results:
  807  *     Err, if < 0.
  808  *     Number of bytes peeked, if >= 0.
  809  *
  810  * Side effects:
  811  *     None.
  812  *
  813  *------------------------------------------------------------------------------
  814  */
  815 
  816 ssize_t
  817 vmci_qpair_peekv(struct vmci_qpair *qpair, void *iov, size_t iov_size,
  818     int buf_type)
  819 {
  820         ssize_t result;
  821 
  822         if (!qpair || !iov)
  823                 return (VMCI_ERROR_INVALID_ARGS);
  824 
  825         result = dequeue(qpair->produce_q, qpair->consume_q,
  826             qpair->consume_q_size, iov, iov_size, buf_type,
  827             qpair->flags & VMCI_QPFLAG_LOCAL?
  828             vmci_memcpy_from_queue_v_local : vmci_memcpy_from_queue_v, false,
  829             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
  830 
  831         return (result);
  832 }

Cache object: c0ff588dc80d82f2fd8c26d760dcf49e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.