~n-muench/ubuntu/precise/open-vm-tools/open-vm-tools.raring-precise.backport

« back to all changes in this revision

Viewing changes to modules/linux/vmci/common/vmciQPair.c

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
66
66
#include "vmci_handle_array.h"
67
67
#include "vmci_defs.h"
68
68
#include "vmciKernelAPI.h"
 
69
#include "vmciQueue.h"
69
70
#include "vmciQueuePair.h"
70
71
#include "vmciRoute.h"
71
72
 
 
73
 
72
74
/*
73
75
 * VMCIQPair
74
76
 *
85
87
   uint32 flags;
86
88
   VMCIPrivilegeFlags privFlags;
87
89
   Bool guestEndpoint;
 
90
   uint32 blocked;
 
91
   VMCIEvent event;
88
92
};
89
93
 
90
 
#define VMCI_QPAIR_NO_QUEUE(_qp) (!(_qp)->produceQ->qHeader || \
91
 
                                  !(_qp)->consumeQ->qHeader)
 
94
static int VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, VMCIQueue *consumeQ,
 
95
                                    Bool canBlock);
 
96
static int VMCIQPairGetQueueHeaders(const VMCIQPair *qpair,
 
97
                                    VMCIQueueHeader **produceQHeader,
 
98
                                    VMCIQueueHeader **consumeQHeader);
 
99
static int VMCIQPairWakeupCB(void *clientData);
 
100
static int VMCIQPairReleaseMutexCB(void *clientData);
 
101
static Bool VMCIQPairWaitForReadyQueue(VMCIQPair *qpair);
 
102
 
 
103
 
 
104
/*
 
105
 *-----------------------------------------------------------------------------
 
106
 *
 
107
 * VMCIQPairLock --
 
108
 *
 
109
 *      Helper routine that will lock the QPair before subsequent operations.
 
110
 *
 
111
 * Results:
 
112
 *      VMCI_SUCCESS if lock acquired. VMCI_ERROR_WOULD_BLOCK if queue mutex
 
113
 *      couldn't be acquired and qpair isn't allowed to block.
 
114
 *
 
115
 * Side effects:
 
116
 *      May block.
 
117
 *
 
118
 *-----------------------------------------------------------------------------
 
119
 */
 
120
 
 
121
static INLINE int
 
122
VMCIQPairLock(const VMCIQPair *qpair) // IN
 
123
{
 
124
#if !defined VMX86_VMX
 
125
   if (qpair->flags & VMCI_QPFLAG_PINNED) {
 
126
      VMCI_LockQueueHeader(qpair->produceQ);
 
127
      return VMCI_SUCCESS;
 
128
   }
 
129
   return VMCI_AcquireQueueMutex(qpair->produceQ,
 
130
                                 !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
131
#else
 
132
   return VMCI_SUCCESS
 
133
#endif
 
134
}
 
135
 
 
136
 
 
137
/*
 
138
 *-----------------------------------------------------------------------------
 
139
 *
 
140
 * VMCIQPairUnlock --
 
141
 *
 
142
 *      Helper routine that will unlock the QPair after various operations.
 
143
 *
 
144
 * Results:
 
145
 *      None.
 
146
 *
 
147
 * Side effects:
 
148
 *      None.
 
149
 *
 
150
 *-----------------------------------------------------------------------------
 
151
 */
 
152
 
 
153
static INLINE void
 
154
VMCIQPairUnlock(const VMCIQPair *qpair) // IN
 
155
{
 
156
#if !defined VMX86_VMX
 
157
   if (qpair->flags & VMCI_QPFLAG_PINNED) {
 
158
      VMCI_UnlockQueueHeader(qpair->produceQ);
 
159
   } else {
 
160
      VMCI_ReleaseQueueMutex(qpair->produceQ);
 
161
   }
 
162
#endif
 
163
}
 
164
 
 
165
 
 
166
/*
 
167
 *-----------------------------------------------------------------------------
 
168
 *
 
169
 * VMCIQPairHeaderLock --
 
170
 *
 
171
 *      Helper routine that will lock the queue pair header before subsequent
 
172
 *      operations. If the queue pair is non blocking, a spinlock will be used.
 
173
 *      Otherwise, a regular mutex locking the complete queue pair will be used.
 
174
 *
 
175
 * Results:
 
176
 *      None.
 
177
 *
 
178
 * Side effects:
 
179
 *      May block.
 
180
 *
 
181
 *-----------------------------------------------------------------------------
 
182
 */
 
183
 
 
184
static INLINE void
 
185
VMCIQPairLockHeader(const VMCIQPair *qpair) // IN
 
186
{
 
187
#if !defined VMX86_VMX
 
188
   if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
 
189
      VMCI_LockQueueHeader(qpair->produceQ);
 
190
   } else {
 
191
      (void)VMCI_AcquireQueueMutex(qpair->produceQ,
 
192
                                   !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
193
   }
 
194
#endif
 
195
}
 
196
 
 
197
 
 
198
/*
 
199
 *-----------------------------------------------------------------------------
 
200
 *
 
201
 * VMCIQPairUnlockHeader --
 
202
 *
 
203
 *      Helper routine that unlocks the queue pair header after calling
 
204
 *      VMCIQPairHeaderLock.
 
205
 *
 
206
 * Results:
 
207
 *      None.
 
208
 *
 
209
 * Side effects:
 
210
 *      None.
 
211
 *
 
212
 *-----------------------------------------------------------------------------
 
213
 */
 
214
 
 
215
static INLINE void
 
216
VMCIQPairUnlockHeader(const VMCIQPair *qpair) // IN
 
217
{
 
218
#if !defined VMX86_VMX
 
219
   if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
 
220
      VMCI_UnlockQueueHeader(qpair->produceQ);
 
221
   } else {
 
222
      VMCI_ReleaseQueueMutex(qpair->produceQ);
 
223
   }
 
224
#endif
 
225
}
 
226
 
 
227
 
 
228
/*
 
229
 *-----------------------------------------------------------------------------
 
230
 *
 
231
 * VMCIQPairGetQueueHeaders --
 
232
 *
 
233
 *      Helper routine that will retrieve the produce and consume
 
234
 *      headers of a given queue pair. If the guest memory of the
 
235
 *      queue pair is currently not available, the saved queue headers
 
236
 *      will be returned, if these are available.
 
237
 *
 
238
 * Results:
 
239
 *      VMCI_SUCCESS if either current or saved queue headers are found.
 
240
 *      Appropriate error code otherwise.
 
241
 *
 
242
 * Side effects:
 
243
 *      May block.
 
244
 *
 
245
 *-----------------------------------------------------------------------------
 
246
 */
 
247
 
 
248
static int
 
249
VMCIQPairGetQueueHeaders(const VMCIQPair *qpair,            // IN
 
250
                         VMCIQueueHeader **produceQHeader,  // OUT
 
251
                         VMCIQueueHeader **consumeQHeader)  // OUT
 
252
{
 
253
   int result;
 
254
 
 
255
   result = VMCIQPairMapQueueHeaders(qpair->produceQ, qpair->consumeQ,
 
256
                                     !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
257
   if (result == VMCI_SUCCESS) {
 
258
      *produceQHeader = qpair->produceQ->qHeader;
 
259
      *consumeQHeader = qpair->consumeQ->qHeader;
 
260
   } else if (qpair->produceQ->savedHeader && qpair->consumeQ->savedHeader) {
 
261
      ASSERT(!qpair->guestEndpoint);
 
262
      *produceQHeader = qpair->produceQ->savedHeader;
 
263
      *consumeQHeader = qpair->consumeQ->savedHeader;
 
264
      result = VMCI_SUCCESS;
 
265
   }
 
266
 
 
267
   return result;
 
268
}
 
269
 
 
270
 
 
271
/*
 
272
 *-----------------------------------------------------------------------------
 
273
 *
 
274
 * VMCIQPairMapQueueHeaders --
 
275
 *
 
276
 *      The queue headers may not be mapped at all times. If a queue is
 
277
 *      currently not mapped, it will be attempted to do so.
 
278
 *
 
279
 * Results:
 
280
 *      VMCI_SUCCESS if queues were validated, appropriate error code otherwise.
 
281
 *
 
282
 * Side effects:
 
283
 *      May attempt to map in guest memory.
 
284
 *
 
285
 *-----------------------------------------------------------------------------
 
286
 */
 
287
 
 
288
static int
 
289
VMCIQPairMapQueueHeaders(VMCIQueue *produceQ, // IN
 
290
                         VMCIQueue *consumeQ, // IN
 
291
                         Bool canBlock)       // IN
 
292
{
 
293
   int result;
 
294
 
 
295
   if (NULL == produceQ->qHeader || NULL == consumeQ->qHeader) {
 
296
      if (canBlock) {
 
297
         result = VMCIHost_MapQueues(produceQ, consumeQ, 0);
 
298
      } else {
 
299
         result = VMCI_ERROR_QUEUEPAIR_NOT_READY;
 
300
      }
 
301
      if (result < VMCI_SUCCESS) {
 
302
         if (produceQ->savedHeader && consumeQ->savedHeader) {
 
303
            return VMCI_ERROR_QUEUEPAIR_NOT_READY;
 
304
         } else {
 
305
            return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
 
306
         }
 
307
      }
 
308
   }
 
309
 
 
310
   return VMCI_SUCCESS;
 
311
}
 
312
 
 
313
 
 
314
/*
 
315
 *-----------------------------------------------------------------------------
 
316
 *
 
317
 * VMCIQPairWakeupCB --
 
318
 *
 
319
 *      Callback from VMCI queue pair broker indicating that a queue
 
320
 *      pair that was previously not ready, now either is ready or
 
321
 *      gone forever.
 
322
 *
 
323
 * Results:
 
324
 *      VMCI_SUCCESS always.
 
325
 *
 
326
 * Side effects:
 
327
 *      None.
 
328
 *
 
329
 *-----------------------------------------------------------------------------
 
330
 */
 
331
 
 
332
static int
 
333
VMCIQPairWakeupCB(void *clientData)
 
334
{
 
335
   VMCIQPair *qpair = (VMCIQPair *)clientData;
 
336
   ASSERT(qpair);
 
337
 
 
338
   VMCIQPairLock(qpair);
 
339
   while (qpair->blocked > 0) {
 
340
      qpair->blocked--;
 
341
      VMCI_SignalEvent(&qpair->event);
 
342
   }
 
343
   VMCIQPairUnlock(qpair);
 
344
 
 
345
   return VMCI_SUCCESS;
 
346
}
 
347
 
 
348
 
 
349
/*
 
350
 *-----------------------------------------------------------------------------
 
351
 *
 
352
 * VMCIQPairReleaseMutexCB --
 
353
 *
 
354
 *      Callback from VMCI_WaitOnEvent releasing the queue pair mutex
 
355
 *      protecting the queue pair header state.
 
356
 *
 
357
 * Results:
 
358
 *      0 always.
 
359
 *
 
360
 * Side effects:
 
361
 *      None.
 
362
 *
 
363
 *-----------------------------------------------------------------------------
 
364
 */
 
365
 
 
366
static int
 
367
VMCIQPairReleaseMutexCB(void *clientData)
 
368
{
 
369
   VMCIQPair *qpair = (VMCIQPair *)clientData;
 
370
   ASSERT(qpair);
 
371
   VMCIQPairUnlock(qpair);
 
372
   return 0;
 
373
}
 
374
 
 
375
 
 
376
/*
 
377
 *-----------------------------------------------------------------------------
 
378
 *
 
379
 * VMCIQPairWaitForReadyQueue --
 
380
 *
 
381
 *      Makes the calling thread wait for the queue pair to become
 
382
 *      ready for host side access.
 
383
 *
 
384
 * Results:
 
385
 *     TRUE when thread is woken up after queue pair state change.
 
386
 *     FALSE otherwise.
 
387
 *
 
388
 * Side effects:
 
389
 *      None.
 
390
 *
 
391
 *-----------------------------------------------------------------------------
 
392
 */
 
393
 
 
394
static Bool
 
395
VMCIQPairWaitForReadyQueue(VMCIQPair *qpair)
 
396
{
 
397
   if (UNLIKELY(qpair->guestEndpoint)) {
 
398
      ASSERT(FALSE);
 
399
      return FALSE;
 
400
   }
 
401
   if (qpair->flags & VMCI_QPFLAG_NONBLOCK) {
 
402
      return FALSE;
 
403
   }
 
404
   qpair->blocked++;
 
405
   VMCI_WaitOnEvent(&qpair->event, VMCIQPairReleaseMutexCB, qpair);
 
406
   VMCIQPairLock(qpair);
 
407
   return TRUE;
 
408
}
92
409
 
93
410
 
94
411
/*
127
444
   VMCIHandle src = VMCI_INVALID_HANDLE;
128
445
   VMCIHandle dst = VMCI_MAKE_HANDLE(peer, VMCI_INVALID_ID);
129
446
   VMCIRoute route;
 
447
   VMCIEventReleaseCB wakeupCB;
 
448
   void *clientData;
130
449
 
131
450
   /*
132
451
    * Restrict the size of a queuepair.  The device already enforces a limit
149
468
      return VMCI_ERROR_NO_RESOURCES;
150
469
   }
151
470
 
 
471
   retval = VMCI_Route(&src, &dst, FALSE, &route);
 
472
   if (retval < VMCI_SUCCESS) {
 
473
      if (VMCI_GuestPersonalityActive()) {
 
474
         route = VMCI_ROUTE_AS_GUEST;
 
475
      } else {
 
476
         route = VMCI_ROUTE_AS_HOST;
 
477
      }
 
478
   }
 
479
 
 
480
   if ((flags & (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED)) && !vmkernel) {
 
481
#if defined(linux)
 
482
      if (VMCI_ROUTE_AS_GUEST != route)
 
483
#endif // linux
 
484
      {
 
485
         return VMCI_ERROR_INVALID_ARGS;
 
486
      }
 
487
   }
 
488
 
 
489
   if (flags & VMCI_QPFLAG_PINNED) {
 
490
      /*
 
491
       * Pinned pages implies non-blocking mode.  Technically it doesn't
 
492
       * have to, but there doesn't seem much point in pinning the pages if you
 
493
       * can block since the queues will be small, so there's no performance
 
494
       * gain to be had.
 
495
       */
 
496
 
 
497
      if (!(flags & VMCI_QPFLAG_NONBLOCK)) {
 
498
         return VMCI_ERROR_INVALID_ARGS;
 
499
      }
 
500
 
 
501
      /* Limit the amount of memory that can be pinned. */
 
502
 
 
503
      if (produceQSize + consumeQSize > VMCI_MAX_PINNED_QP_MEMORY) {
 
504
         return VMCI_ERROR_NO_RESOURCES;
 
505
      }
 
506
   }
 
507
 
152
508
   myQPair = VMCI_AllocKernelMem(sizeof *myQPair, VMCI_MEMORY_NONPAGED);
153
509
   if (!myQPair) {
154
510
      return VMCI_ERROR_NO_MEM;
161
517
   myQPair->flags = flags;
162
518
   myQPair->privFlags = privFlags;
163
519
 
164
 
   retval = VMCI_Route(&src, &dst, FALSE, &route);
165
 
   if (retval < VMCI_SUCCESS) {
166
 
      if (VMCI_GuestPersonalityActive()) {
167
 
         route = VMCI_ROUTE_AS_GUEST;
168
 
      } else {
169
 
         route = VMCI_ROUTE_AS_HOST;
170
 
      }
171
 
   }
172
 
 
 
520
   wakeupCB = clientData = NULL;
173
521
   if (VMCI_ROUTE_AS_HOST == route) {
174
522
      myQPair->guestEndpoint = FALSE;
 
523
      if (!(flags & VMCI_QPFLAG_LOCAL)) {
 
524
         myQPair->blocked = 0;
 
525
         VMCI_CreateEvent(&myQPair->event);
 
526
         wakeupCB = VMCIQPairWakeupCB;
 
527
         clientData = (void *)myQPair;
 
528
      }
175
529
   } else {
176
530
      myQPair->guestEndpoint = TRUE;
177
531
   }
184
538
                                myQPair->peer,
185
539
                                myQPair->flags,
186
540
                                myQPair->privFlags,
187
 
                                myQPair->guestEndpoint);
 
541
                                myQPair->guestEndpoint,
 
542
                                wakeupCB,
 
543
                                clientData);
188
544
 
189
545
   if (retval < VMCI_SUCCESS) {
 
546
      if (VMCI_ROUTE_AS_HOST == route && !(flags & VMCI_QPFLAG_LOCAL)) {
 
547
         VMCI_DestroyEvent(&myQPair->event);
 
548
      }
190
549
      VMCI_FreeKernelMem(myQPair, sizeof *myQPair);
191
550
      return retval;
192
551
   }
238
597
    * there isn't much the caller can do, and we don't want to leak.
239
598
    */
240
599
 
 
600
   if (!(oldQPair->guestEndpoint || (oldQPair->flags & VMCI_QPFLAG_LOCAL))) {
 
601
      VMCI_DestroyEvent(&oldQPair->event);
 
602
   }
241
603
   memset(oldQPair, 0, sizeof *oldQPair);
242
604
   oldQPair->handle = VMCI_INVALID_HANDLE;
243
605
   oldQPair->peer = VMCI_INVALID_ID;
249
611
 
250
612
 
251
613
/*
252
 
 * "Windows blocking call."
253
 
 *
254
 
 *      Note that on the Windows platform, kernel module clients may
255
 
 *      block when calling into any these rouintes.  The reason is
256
 
 *      that a mutex has to be acquired in order to view/modify the
257
 
 *      VMCIQueue structure fields: pointers, handle, and buffer data.
258
 
 *      However, other platforms don't require the acquisition of a
259
 
 *      mutex and thus don't block.
260
 
 */
261
 
 
262
 
 
263
 
/*
264
 
 *-----------------------------------------------------------------------------
265
 
 *
266
 
 * VMCIQPair_Lock --
267
 
 *
268
 
 *      Helper routine that will lock the QPair before subsequent operations.
269
 
 *
270
 
 * Results:
271
 
 *      None.
272
 
 *
273
 
 * Side effects:
274
 
 *      Windows blocking call.
275
 
 *
276
 
 *-----------------------------------------------------------------------------
277
 
 */
278
 
 
279
 
static INLINE void
280
 
VMCIQPairLock(const VMCIQPair *qpair) // IN
281
 
{
282
 
#if !defined VMX86_VMX
283
 
   VMCI_AcquireQueueMutex(qpair->produceQ);
284
 
#endif
285
 
}
286
 
 
287
 
 
288
 
/*
289
 
 *-----------------------------------------------------------------------------
290
 
 *
291
 
 * VMCIQPair_Unlock --
292
 
 *
293
 
 *      Helper routine that will unlock the QPair after various operations.
294
 
 *
295
 
 * Results:
296
 
 *      None.
297
 
 *
298
 
 * Side effects:
299
 
 *      None.
300
 
 *
301
 
 *-----------------------------------------------------------------------------
302
 
 */
303
 
 
304
 
static INLINE void
305
 
VMCIQPairUnlock(const VMCIQPair *qpair) // IN
306
 
{
307
 
#if !defined VMX86_VMX
308
 
   VMCI_ReleaseQueueMutex(qpair->produceQ);
309
 
#endif
310
 
}
311
 
 
312
 
 
313
 
/*
314
614
 *-----------------------------------------------------------------------------
315
615
 *
316
616
 * VMCIQPair_GetProduceIndexes --
334
634
                            uint64 *producerTail,   // OUT
335
635
                            uint64 *consumerHead)   // OUT
336
636
{
 
637
   VMCIQueueHeader *produceQHeader;
 
638
   VMCIQueueHeader *consumeQHeader;
337
639
   int result;
338
640
 
339
641
   if (!qpair) {
340
642
      return VMCI_ERROR_INVALID_ARGS;
341
643
   }
342
644
 
343
 
   VMCIQPairLock(qpair);
344
 
 
345
 
   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
346
 
      result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
347
 
   } else {
348
 
      VMCIQueueHeader_GetPointers(qpair->produceQ->qHeader,
349
 
                                  qpair->consumeQ->qHeader,
350
 
                                  producerTail,
351
 
                                  consumerHead);
352
 
      result = VMCI_SUCCESS;
 
645
   VMCIQPairLockHeader(qpair);
 
646
   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
 
647
   if (result == VMCI_SUCCESS) {
 
648
      VMCIQueueHeader_GetPointers(produceQHeader, consumeQHeader,
 
649
                                  producerTail, consumerHead);
353
650
   }
354
 
 
355
 
   VMCIQPairUnlock(qpair);
 
651
   VMCIQPairUnlockHeader(qpair);
356
652
 
357
653
   if (result == VMCI_SUCCESS &&
358
654
       ((producerTail && *producerTail >= qpair->produceQSize) ||
388
684
                            uint64 *consumerTail,   // OUT
389
685
                            uint64 *producerHead)   // OUT
390
686
{
 
687
   VMCIQueueHeader *produceQHeader;
 
688
   VMCIQueueHeader *consumeQHeader;
391
689
   int result;
392
690
 
393
691
   if (!qpair) {
394
692
      return VMCI_ERROR_INVALID_ARGS;
395
693
   }
396
694
 
397
 
   VMCIQPairLock(qpair);
398
 
 
399
 
   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
400
 
      result = VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
401
 
   } else {
402
 
      VMCIQueueHeader_GetPointers(qpair->consumeQ->qHeader,
403
 
                                  qpair->produceQ->qHeader,
404
 
                                  consumerTail,
405
 
                                  producerHead);
406
 
      result = VMCI_SUCCESS;
 
695
   VMCIQPairLockHeader(qpair);
 
696
   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
 
697
   if (result == VMCI_SUCCESS) {
 
698
      VMCIQueueHeader_GetPointers(consumeQHeader, produceQHeader,
 
699
                                  consumerTail, producerHead);
407
700
   }
408
 
 
409
 
   VMCIQPairUnlock(qpair);
 
701
   VMCIQPairUnlockHeader(qpair);
410
702
 
411
703
   if (result == VMCI_SUCCESS &&
412
704
       ((consumerTail && *consumerTail >= qpair->consumeQSize) ||
442
734
int64
443
735
VMCIQPair_ProduceFreeSpace(const VMCIQPair *qpair) // IN
444
736
{
 
737
   VMCIQueueHeader *produceQHeader;
 
738
   VMCIQueueHeader *consumeQHeader;
445
739
   int64 result;
446
740
 
447
741
   if (!qpair) {
448
742
      return VMCI_ERROR_INVALID_ARGS;
449
743
   }
450
744
 
451
 
   VMCIQPairLock(qpair);
452
 
 
453
 
   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
454
 
      result = 0;
455
 
   } else {
456
 
      result = VMCIQueueHeader_FreeSpace(qpair->produceQ->qHeader,
457
 
                                         qpair->consumeQ->qHeader,
 
745
   VMCIQPairLockHeader(qpair);
 
746
   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
 
747
   if (result == VMCI_SUCCESS) {
 
748
      result = VMCIQueueHeader_FreeSpace(produceQHeader, consumeQHeader,
458
749
                                         qpair->produceQSize);
 
750
   } else {
 
751
      result = 0;
459
752
   }
460
 
 
461
 
   VMCIQPairUnlock(qpair);
 
753
   VMCIQPairUnlockHeader(qpair);
462
754
 
463
755
   return result;
464
756
}
489
781
int64
490
782
VMCIQPair_ConsumeFreeSpace(const VMCIQPair *qpair) // IN
491
783
{
 
784
   VMCIQueueHeader *produceQHeader;
 
785
   VMCIQueueHeader *consumeQHeader;
492
786
   int64 result;
493
787
 
494
788
   if (!qpair) {
495
789
      return VMCI_ERROR_INVALID_ARGS;
496
790
   }
497
791
 
498
 
   VMCIQPairLock(qpair);
499
 
 
500
 
   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
501
 
      result = 0;
502
 
   } else {
503
 
      result = VMCIQueueHeader_FreeSpace(qpair->consumeQ->qHeader,
504
 
                                         qpair->produceQ->qHeader,
 
792
   VMCIQPairLockHeader(qpair);
 
793
   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
 
794
   if (result == VMCI_SUCCESS) {
 
795
      result = VMCIQueueHeader_FreeSpace(consumeQHeader, produceQHeader,
505
796
                                         qpair->consumeQSize);
 
797
   } else {
 
798
      result = 0;
506
799
   }
507
 
 
508
 
   VMCIQPairUnlock(qpair);
 
800
   VMCIQPairUnlockHeader(qpair);
509
801
 
510
802
   return result;
511
803
}
536
828
int64
537
829
VMCIQPair_ProduceBufReady(const VMCIQPair *qpair) // IN
538
830
{
 
831
   VMCIQueueHeader *produceQHeader;
 
832
   VMCIQueueHeader *consumeQHeader;
539
833
   int64 result;
540
834
 
541
835
   if (!qpair) {
542
836
      return VMCI_ERROR_INVALID_ARGS;
543
837
   }
544
838
 
545
 
   VMCIQPairLock(qpair);
546
 
 
547
 
   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
548
 
      result = 0;
549
 
   } else {
550
 
      result = VMCIQueueHeader_BufReady(qpair->produceQ->qHeader,
551
 
                                        qpair->consumeQ->qHeader,
 
839
   VMCIQPairLockHeader(qpair);
 
840
   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
 
841
   if (result == VMCI_SUCCESS) {
 
842
      result = VMCIQueueHeader_BufReady(produceQHeader, consumeQHeader,
552
843
                                        qpair->produceQSize);
 
844
   } else {
 
845
      result = 0;
553
846
   }
554
 
 
555
 
   VMCIQPairUnlock(qpair);
 
847
   VMCIQPairUnlockHeader(qpair);
556
848
 
557
849
   return result;
558
850
}
582
874
int64
583
875
VMCIQPair_ConsumeBufReady(const VMCIQPair *qpair) // IN
584
876
{
 
877
   VMCIQueueHeader *produceQHeader;
 
878
   VMCIQueueHeader *consumeQHeader;
585
879
   int64 result;
586
880
 
587
881
   if (!qpair) {
588
882
      return VMCI_ERROR_INVALID_ARGS;
589
883
   }
590
884
 
591
 
   VMCIQPairLock(qpair);
592
 
 
593
 
   if (UNLIKELY(VMCI_QPAIR_NO_QUEUE(qpair))) {
594
 
      result = 0;
595
 
   } else {
596
 
      result = VMCIQueueHeader_BufReady(qpair->consumeQ->qHeader,
597
 
                                        qpair->produceQ->qHeader,
 
885
   VMCIQPairLockHeader(qpair);
 
886
   result = VMCIQPairGetQueueHeaders(qpair, &produceQHeader, &consumeQHeader);
 
887
   if (result == VMCI_SUCCESS) {
 
888
      result = VMCIQueueHeader_BufReady(consumeQHeader, produceQHeader,
598
889
                                        qpair->consumeQSize);
 
890
   } else {
 
891
      result = 0;
599
892
   }
600
 
 
601
 
   VMCIQPairUnlock(qpair);
 
893
   VMCIQPairUnlockHeader(qpair);
602
894
 
603
895
   return result;
604
896
}
632
924
 
633
925
static INLINE ssize_t
634
926
EnqueueLocked(VMCIQueue *produceQ,                   // IN
635
 
              const VMCIQueue *consumeQ,             // IN
 
927
              VMCIQueue *consumeQ,                   // IN
636
928
              const uint64 produceQSize,             // IN
637
929
              const void *buf,                       // IN
638
930
              size_t bufSize,                        // IN
639
931
              int bufType,                           // IN
640
 
              VMCIMemcpyToQueueFunc memcpyToQueue)   // IN
 
932
              VMCIMemcpyToQueueFunc memcpyToQueue,   // IN
 
933
              Bool canBlock)                         // IN
641
934
{
642
935
   int64 freeSpace;
643
936
   uint64 tail;
649
942
      return (ssize_t) bufSize;
650
943
   }
651
944
 
652
 
   if (UNLIKELY(!produceQ->qHeader || !consumeQ->qHeader)) {
653
 
      return VMCI_ERROR_QUEUEPAIR_NOTATTACHED;
 
945
   result = VMCIQPairMapQueueHeaders(produceQ, consumeQ, canBlock);
 
946
   if (UNLIKELY(result != VMCI_SUCCESS)) {
 
947
      return result;
654
948
   }
655
949
#endif
656
950
 
668
962
   written = (size_t)(freeSpace > bufSize ? bufSize : freeSpace);
669
963
   tail = VMCIQueueHeader_ProducerTail(produceQ->qHeader);
670
964
   if (LIKELY(tail + written < produceQSize)) {
671
 
      result = memcpyToQueue(produceQ, tail, buf, 0, written, bufType);
 
965
      result = memcpyToQueue(produceQ, tail, buf, 0, written, bufType,
 
966
                             canBlock);
672
967
   } else {
673
968
      /* Tail pointer wraps around. */
674
969
 
675
970
      const size_t tmp = (size_t)(produceQSize - tail);
676
971
 
677
 
      result = memcpyToQueue(produceQ, tail, buf, 0, tmp, bufType);
 
972
      result = memcpyToQueue(produceQ, tail, buf, 0, tmp, bufType, canBlock);
678
973
      if (result >= VMCI_SUCCESS) {
679
 
         result = memcpyToQueue(produceQ, 0, buf, tmp, written - tmp, bufType);
 
974
         result = memcpyToQueue(produceQ, 0, buf, tmp, written - tmp, bufType,
 
975
                                canBlock);
680
976
      }
681
977
   }
682
978
 
714
1010
 
715
1011
static INLINE ssize_t
716
1012
DequeueLocked(VMCIQueue *produceQ,                        // IN
717
 
              const VMCIQueue *consumeQ,                  // IN
 
1013
              VMCIQueue *consumeQ,                        // IN
718
1014
              const uint64 consumeQSize,                  // IN
719
1015
              void *buf,                                  // IN
720
1016
              size_t bufSize,                             // IN
721
1017
              int bufType,                                // IN
722
1018
              VMCIMemcpyFromQueueFunc memcpyFromQueue,    // IN
723
 
              Bool updateConsumer)                        // IN
 
1019
              Bool updateConsumer,                        // IN
 
1020
              Bool canBlock)                              // IN
724
1021
{
725
1022
   int64 bufReady;
726
1023
   uint64 head;
728
1025
   ssize_t result;
729
1026
 
730
1027
#if !defined VMX86_VMX
731
 
   if (UNLIKELY(!produceQ->qHeader ||
732
 
                !consumeQ->qHeader)) {
733
 
      return VMCI_ERROR_QUEUEPAIR_NODATA;
 
1028
   result = VMCIQPairMapQueueHeaders(produceQ, consumeQ, canBlock);
 
1029
   if (UNLIKELY(result != VMCI_SUCCESS)) {
 
1030
      return result;
734
1031
   }
735
1032
#endif
736
1033
 
747
1044
   read = (size_t)(bufReady > bufSize ? bufSize : bufReady);
748
1045
   head = VMCIQueueHeader_ConsumerHead(produceQ->qHeader);
749
1046
   if (LIKELY(head + read < consumeQSize)) {
750
 
      result = memcpyFromQueue(buf, 0, consumeQ, head, read, bufType);
 
1047
      result = memcpyFromQueue(buf, 0, consumeQ, head, read, bufType, canBlock);
751
1048
   } else {
752
1049
      /* Head pointer wraps around. */
753
1050
 
754
1051
      const size_t tmp = (size_t)(consumeQSize - head);
755
1052
 
756
 
      result = memcpyFromQueue(buf, 0, consumeQ, head, tmp, bufType);
 
1053
      result = memcpyFromQueue(buf, 0, consumeQ, head, tmp, bufType, canBlock);
757
1054
      if (result >= VMCI_SUCCESS) {
758
 
         result = memcpyFromQueue(buf, tmp, consumeQ, 0, read - tmp, bufType);
 
1055
         result = memcpyFromQueue(buf, tmp, consumeQ, 0, read - tmp, bufType,
 
1056
                                  canBlock);
759
1057
      }
760
1058
   }
761
1059
 
803
1101
      return VMCI_ERROR_INVALID_ARGS;
804
1102
   }
805
1103
 
806
 
   VMCIQPairLock(qpair);
 
1104
   result = VMCIQPairLock(qpair);
 
1105
   if (result != VMCI_SUCCESS) {
 
1106
      return result;
 
1107
   }
807
1108
 
808
 
   result = EnqueueLocked(qpair->produceQ,
809
 
                          qpair->consumeQ,
810
 
                          qpair->produceQSize,
811
 
                          buf, bufSize, bufType,
812
 
                          VMCIMemcpyToQueue);
 
1109
   do {
 
1110
      result = EnqueueLocked(qpair->produceQ,
 
1111
                             qpair->consumeQ,
 
1112
                             qpair->produceQSize,
 
1113
                             buf, bufSize, bufType,
 
1114
                             qpair->flags & VMCI_QPFLAG_LOCAL?
 
1115
                             VMCIMemcpyToQueueLocal:
 
1116
                             VMCIMemcpyToQueue,
 
1117
                             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
1118
      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
 
1119
         if (!VMCIQPairWaitForReadyQueue(qpair)) {
 
1120
            result = VMCI_ERROR_WOULD_BLOCK;
 
1121
         }
 
1122
      }
 
1123
   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
813
1124
 
814
1125
   VMCIQPairUnlock(qpair);
815
1126
 
847
1158
      return VMCI_ERROR_INVALID_ARGS;
848
1159
   }
849
1160
 
850
 
   VMCIQPairLock(qpair);
 
1161
   result = VMCIQPairLock(qpair);
 
1162
   if (result != VMCI_SUCCESS) {
 
1163
      return result;
 
1164
   }
851
1165
 
852
 
   result = DequeueLocked(qpair->produceQ,
853
 
                          qpair->consumeQ,
854
 
                          qpair->consumeQSize,
855
 
                          buf, bufSize, bufType,
856
 
                          VMCIMemcpyFromQueue,
857
 
                          TRUE);
 
1166
   do {
 
1167
      result = DequeueLocked(qpair->produceQ,
 
1168
                             qpair->consumeQ,
 
1169
                             qpair->consumeQSize,
 
1170
                             buf, bufSize, bufType,
 
1171
                             qpair->flags & VMCI_QPFLAG_LOCAL?
 
1172
                             VMCIMemcpyFromQueueLocal:
 
1173
                             VMCIMemcpyFromQueue,
 
1174
                             TRUE, !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
1175
      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
 
1176
         if (!VMCIQPairWaitForReadyQueue(qpair)) {
 
1177
            result = VMCI_ERROR_WOULD_BLOCK;
 
1178
         }
 
1179
      }
 
1180
   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
858
1181
 
859
1182
   VMCIQPairUnlock(qpair);
860
1183
 
893
1216
      return VMCI_ERROR_INVALID_ARGS;
894
1217
   }
895
1218
 
896
 
   VMCIQPairLock(qpair);
 
1219
   result = VMCIQPairLock(qpair);
 
1220
   if (result != VMCI_SUCCESS) {
 
1221
      return result;
 
1222
   }
897
1223
 
898
 
   result = DequeueLocked(qpair->produceQ,
899
 
                          qpair->consumeQ,
900
 
                          qpair->consumeQSize,
901
 
                          buf, bufSize, bufType,
902
 
                          VMCIMemcpyFromQueue,
903
 
                          FALSE);
 
1224
   do {
 
1225
      result = DequeueLocked(qpair->produceQ,
 
1226
                             qpair->consumeQ,
 
1227
                             qpair->consumeQSize,
 
1228
                             buf, bufSize, bufType,
 
1229
                             qpair->flags & VMCI_QPFLAG_LOCAL?
 
1230
                             VMCIMemcpyFromQueueLocal:
 
1231
                             VMCIMemcpyFromQueue,
 
1232
                             FALSE, !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
1233
      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
 
1234
         if (!VMCIQPairWaitForReadyQueue(qpair)) {
 
1235
            result = VMCI_ERROR_WOULD_BLOCK;
 
1236
         }
 
1237
      }
 
1238
   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
904
1239
 
905
1240
   VMCIQPairUnlock(qpair);
906
1241
 
942
1277
      return VMCI_ERROR_INVALID_ARGS;
943
1278
   }
944
1279
 
945
 
   VMCIQPairLock(qpair);
 
1280
   result = VMCIQPairLock(qpair);
 
1281
   if (result != VMCI_SUCCESS) {
 
1282
      return result;
 
1283
   }
946
1284
 
947
 
   result = EnqueueLocked(qpair->produceQ,
948
 
                          qpair->consumeQ,
949
 
                          qpair->produceQSize,
950
 
                          iov, iovSize, bufType,
951
 
                          VMCIMemcpyToQueueV);
 
1285
   do {
 
1286
      result = EnqueueLocked(qpair->produceQ,
 
1287
                             qpair->consumeQ,
 
1288
                             qpair->produceQSize,
 
1289
                             iov, iovSize, bufType,
 
1290
                             qpair->flags & VMCI_QPFLAG_LOCAL?
 
1291
                             VMCIMemcpyToQueueVLocal:
 
1292
                             VMCIMemcpyToQueueV,
 
1293
                             !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
1294
      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
 
1295
         if (!VMCIQPairWaitForReadyQueue(qpair)) {
 
1296
            result = VMCI_ERROR_WOULD_BLOCK;
 
1297
         }
 
1298
      }
 
1299
   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
952
1300
 
953
1301
   VMCIQPairUnlock(qpair);
954
1302
 
982
1330
{
983
1331
   ssize_t result;
984
1332
 
985
 
   VMCIQPairLock(qpair);
 
1333
   result = VMCIQPairLock(qpair);
 
1334
   if (result != VMCI_SUCCESS) {
 
1335
      return result;
 
1336
   }
986
1337
 
987
1338
   if (!qpair || !iov) {
988
1339
      return VMCI_ERROR_INVALID_ARGS;
989
1340
   }
990
1341
 
991
 
   result = DequeueLocked(qpair->produceQ,
992
 
                          qpair->consumeQ,
993
 
                          qpair->consumeQSize,
994
 
                          iov, iovSize, bufType,
995
 
                          VMCIMemcpyFromQueueV,
996
 
                          TRUE);
 
1342
   do {
 
1343
      result = DequeueLocked(qpair->produceQ,
 
1344
                             qpair->consumeQ,
 
1345
                             qpair->consumeQSize,
 
1346
                             iov, iovSize, bufType,
 
1347
                             qpair->flags & VMCI_QPFLAG_LOCAL?
 
1348
                             VMCIMemcpyFromQueueVLocal:
 
1349
                             VMCIMemcpyFromQueueV,
 
1350
                             TRUE, !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
1351
      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
 
1352
         if (!VMCIQPairWaitForReadyQueue(qpair)) {
 
1353
            result = VMCI_ERROR_WOULD_BLOCK;
 
1354
         }
 
1355
      }
 
1356
   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
997
1357
 
998
1358
   VMCIQPairUnlock(qpair);
999
1359
 
1032
1392
      return VMCI_ERROR_INVALID_ARGS;
1033
1393
   }
1034
1394
 
1035
 
   VMCIQPairLock(qpair);
 
1395
   result = VMCIQPairLock(qpair);
 
1396
   if (result != VMCI_SUCCESS) {
 
1397
      return result;
 
1398
   }
1036
1399
 
1037
 
   result = DequeueLocked(qpair->produceQ,
1038
 
                          qpair->consumeQ,
1039
 
                          qpair->consumeQSize,
1040
 
                          iov, iovSize, bufType,
1041
 
                          VMCIMemcpyFromQueueV,
1042
 
                          FALSE);
 
1400
   do {
 
1401
      result = DequeueLocked(qpair->produceQ,
 
1402
                             qpair->consumeQ,
 
1403
                             qpair->consumeQSize,
 
1404
                             iov, iovSize, bufType,
 
1405
                             qpair->flags & VMCI_QPFLAG_LOCAL?
 
1406
                             VMCIMemcpyFromQueueVLocal:
 
1407
                             VMCIMemcpyFromQueueV,
 
1408
                             FALSE, !(qpair->flags & VMCI_QPFLAG_NONBLOCK));
 
1409
      if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY) {
 
1410
         if (!VMCIQPairWaitForReadyQueue(qpair)) {
 
1411
            result = VMCI_ERROR_WOULD_BLOCK;
 
1412
         }
 
1413
      }
 
1414
   } while (result == VMCI_ERROR_QUEUEPAIR_NOT_READY);
1043
1415
 
1044
1416
   VMCIQPairUnlock(qpair);
1045
1417