~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/lock/ulRec.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include "userlock.h"
23
23
#include "hostinfo.h"
24
24
#include "ulInt.h"
25
 
 
26
 
#define MXUSER_REC_SIGNATURE 0x43524B4C // 'LKRC' in memory
27
 
 
28
 
struct MXUserRecLock
 
25
#include "vm_atomic.h"
 
26
 
 
27
typedef struct
29
28
{
30
 
   MXUserHeader            header;
31
 
   MXRecLock               recursiveLock;
32
 
 
33
 
   uint64                  holdStart;
34
 
 
35
 
#if defined(MXUSER_STATS)
36
29
   MXUserAcquisitionStats  acquisitionStats;
37
30
   Atomic_Ptr              acquisitionHisto;
38
31
 
 
32
   void                   *holder;
 
33
   uint64                  holdStart;
39
34
   MXUserBasicStats        heldStats;
40
35
   Atomic_Ptr              heldHisto;
41
 
#endif
 
36
} MXUserStats;
 
37
 
 
38
#define MXUSER_REC_SIGNATURE 0x43524B4C // 'LKRC' in memory
 
39
 
 
40
struct MXUserRecLock
 
41
{
 
42
   MXUserHeader         header;
 
43
   MXRecLock            recursiveLock;
 
44
   Atomic_Ptr           statsMem;
42
45
 
43
46
   /*
44
47
    * This is the MX recursive lock override pointer. It is used within the
51
54
    *         MXUser_BindMXMutexRec was used to create the lock
52
55
    */
53
56
 
54
 
   struct MX_MutexRec     *vmmLock;
 
57
   struct MX_MutexRec  *vmmLock;
55
58
};
56
59
 
57
 
#if defined(MXUSER_STATS)
 
60
 
58
61
/*
59
62
 *-----------------------------------------------------------------------------
60
63
 *
74
77
static void
75
78
MXUserStatsActionRec(MXUserHeader *header)  // IN:
76
79
{
77
 
   Bool isHot;
78
 
   Bool doLog;
79
 
   double contentionRatio;
80
 
 
81
80
   MXUserRecLock *lock = (MXUserRecLock *) header;
82
 
 
83
 
   /*
84
 
    * Dump the statistics for the specified lock.
85
 
    */
86
 
 
87
 
   MXUserDumpAcquisitionStats(&lock->acquisitionStats, header);
88
 
 
89
 
   if (Atomic_ReadPtr(&lock->acquisitionHisto) != NULL) {
90
 
      MXUserHistoDump(Atomic_ReadPtr(&lock->acquisitionHisto), header);
91
 
   }
92
 
 
93
 
   MXUserDumpBasicStats(&lock->heldStats, header);
94
 
 
95
 
   if (Atomic_ReadPtr(&lock->heldHisto) != NULL) {
96
 
      MXUserHistoDump(Atomic_ReadPtr(&lock->heldHisto), header);
97
 
   }
98
 
 
99
 
   /*
100
 
    * Has the lock gone "hot"? If so, implement the hot actions.
101
 
    */
102
 
 
103
 
   MXUserKitchen(&lock->acquisitionStats, &contentionRatio, &isHot, &doLog);
104
 
 
105
 
   if (isHot) {
106
 
      MXUserForceHisto(&lock->acquisitionHisto,
107
 
                       MXUSER_STAT_CLASS_ACQUISITION,
108
 
                       MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
109
 
                       MXUSER_DEFAULT_HISTO_DECADES);
110
 
      MXUserForceHisto(&lock->heldHisto,
111
 
                       MXUSER_STAT_CLASS_HELD,
112
 
                       MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
113
 
                       MXUSER_DEFAULT_HISTO_DECADES);
114
 
 
115
 
      if (doLog) {
116
 
         Log("HOT LOCK (%s); contention ratio %f\n",
117
 
             lock->header.name, contentionRatio);
 
81
   MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
82
 
 
83
   if (stats) {
 
84
      Bool isHot;
 
85
      Bool doLog;
 
86
      double contentionRatio;
 
87
 
 
88
      /*
 
89
       * Dump the statistics for the specified lock.
 
90
       */
 
91
 
 
92
      MXUserDumpAcquisitionStats(&stats->acquisitionStats, header);
 
93
 
 
94
      if (Atomic_ReadPtr(&stats->acquisitionHisto) != NULL) {
 
95
         MXUserHistoDump(Atomic_ReadPtr(&stats->acquisitionHisto), header);
 
96
      }
 
97
 
 
98
      MXUserDumpBasicStats(&stats->heldStats, header);
 
99
 
 
100
      if (Atomic_ReadPtr(&stats->heldHisto) != NULL) {
 
101
         MXUserHistoDump(Atomic_ReadPtr(&stats->heldHisto), header);
 
102
      }
 
103
 
 
104
      /*
 
105
       * Has the lock gone "hot"? If so, implement the hot actions.
 
106
       */
 
107
 
 
108
      MXUserKitchen(&stats->acquisitionStats, &contentionRatio, &isHot,
 
109
                    &doLog);
 
110
 
 
111
      if (isHot) {
 
112
         MXUserForceHisto(&stats->acquisitionHisto,
 
113
                          MXUSER_STAT_CLASS_ACQUISITION,
 
114
                          MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
 
115
                          MXUSER_DEFAULT_HISTO_DECADES);
 
116
         MXUserForceHisto(&stats->heldHisto,
 
117
                          MXUSER_STAT_CLASS_HELD,
 
118
                          MXUSER_DEFAULT_HISTO_MIN_VALUE_NS,
 
119
                          MXUSER_DEFAULT_HISTO_DECADES);
 
120
 
 
121
         if (doLog) {
 
122
            Log("HOT LOCK (%s); contention ratio %f\n",
 
123
                lock->header.name, contentionRatio);
 
124
         }
118
125
      }
119
126
   }
120
127
}
121
 
#endif
122
128
 
123
129
 
124
130
/*
126
132
 *
127
133
 * MXUserDumpRecLock --
128
134
 *
129
 
 *      Dump an recursive lock.
 
135
 *      Dump a recursive lock.
130
136
 *
131
137
 * Results:
132
138
 *      A dump.
147
153
   Warning("\tsignature 0x%X\n", lock->header.signature);
148
154
   Warning("\tname %s\n", lock->header.name);
149
155
   Warning("\trank 0x%X\n", lock->header.rank);
 
156
   Warning("\tserial number %u\n", lock->header.serialNumber);
150
157
 
151
158
   if (lock->vmmLock == NULL) {
 
159
      MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
160
 
152
161
      Warning("\tcount %u\n", lock->recursiveLock.referenceCount);
153
162
 
154
 
#if defined(MXUSER_DEBUG)
155
 
      Warning("\tcaller 0x%p\n", lock->recursiveLock.ownerRetAddr);
156
 
      Warning("\tVThreadID %d\n", (int) lock->recursiveLock.portableThreadID);
 
163
#if defined(_WIN32)
 
164
      Warning("\towner %u\n", lock->recursiveLock.nativeThreadID);
 
165
#else
 
166
      Warning("\towner 0x%p\n",
 
167
              (void *)(uintptr_t)lock->recursiveLock.nativeThreadID);
157
168
#endif
 
169
 
 
170
      if (stats && (stats->holder != NULL)) {
 
171
         Warning("\tholder %p\n", stats->holder);
 
172
      }
158
173
   } else {
159
174
      Warning("\tvmmLock 0x%p\n", lock->vmmLock);
160
175
   }
164
179
/*
165
180
 *-----------------------------------------------------------------------------
166
181
 *
167
 
 * MXUser_CreateRecLock --
168
 
 *
169
 
 *      Create a recursive lock.
 
182
 * MXUser_ControlRecLock --
 
183
 *
 
184
 *      Perform the specified command on the specified lock.
 
185
 *
 
186
 * Results:
 
187
 *      TRUE    succeeded
 
188
 *      FALSE   failed
 
189
 *
 
190
 * Side effects:
 
191
 *      Depends on the command, no?
 
192
 *
 
193
 *-----------------------------------------------------------------------------
 
194
 */
 
195
 
 
196
Bool
 
197
MXUser_ControlRecLock(MXUserRecLock *lock,  // IN/OUT:
 
198
                      uint32 command,       // IN:
 
199
                      ...)                  // IN:
 
200
{
 
201
   Bool result;
 
202
 
 
203
   ASSERT(lock && (lock->header.signature == MXUSER_REC_SIGNATURE));
 
204
 
 
205
   switch (command) {
 
206
   case MXUSER_CONTROL_ACQUISITION_HISTO: {
 
207
      MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
208
 
 
209
      if (stats && (lock->vmmLock == NULL)) {
 
210
         va_list a;
 
211
         uint64 minValue;
 
212
         uint32 decades;
 
213
         va_start(a, command);
 
214
         minValue = va_arg(a, uint64);
 
215
         decades = va_arg(a, uint32);
 
216
         va_end(a);
 
217
 
 
218
         MXUserForceHisto(&stats->acquisitionHisto,
 
219
                          MXUSER_STAT_CLASS_ACQUISITION, minValue, decades);
 
220
 
 
221
         result = TRUE;
 
222
      } else {
 
223
         result = FALSE;
 
224
      }
 
225
      break;
 
226
   }
 
227
 
 
228
   case MXUSER_CONTROL_HELD_HISTO: {
 
229
      MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
230
 
 
231
      if (stats && (lock->vmmLock == NULL)) {
 
232
         va_list a;
 
233
         uint64 minValue;
 
234
         uint32 decades;
 
235
         va_start(a, command);
 
236
         minValue = va_arg(a, uint64);
 
237
         decades = va_arg(a, uint32);
 
238
         va_end(a);
 
239
 
 
240
         MXUserForceHisto(&stats->heldHisto, MXUSER_STAT_CLASS_HELD,
 
241
                          minValue, decades);
 
242
      
 
243
         result = TRUE;
 
244
      } else {
 
245
         result = FALSE;
 
246
      }
 
247
 
 
248
      break; 
 
249
   }
 
250
 
 
251
   case MXUSER_CONTROL_ENABLE_STATS: {
 
252
      MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
253
 
 
254
      if (LIKELY(stats == NULL)) {
 
255
         MXUserStats *before;
 
256
 
 
257
         stats = Util_SafeCalloc(1, sizeof(*stats));
 
258
 
 
259
         MXUserAcquisitionStatsSetUp(&stats->acquisitionStats);
 
260
         MXUserBasicStatsSetUp(&stats->heldStats, MXUSER_STAT_CLASS_HELD);
 
261
 
 
262
         before = (MXUserStats *) Atomic_ReadIfEqualWritePtr(&lock->statsMem,
 
263
                                                             NULL,
 
264
                                                             (void *) stats);
 
265
 
 
266
         if (before) {
 
267
            free(stats);
 
268
         }
 
269
 
 
270
         lock->header.statsFunc = MXUserStatsActionRec;
 
271
      }
 
272
 
 
273
      result = TRUE;
 
274
      break;
 
275
   }
 
276
 
 
277
   default:
 
278
      result = FALSE;
 
279
   }
 
280
 
 
281
   return result;
 
282
}
 
283
 
 
284
 
 
285
/*
 
286
 *-----------------------------------------------------------------------------
 
287
 *
 
288
 * MXUserCreateRecLock --
 
289
 *
 
290
 *      Create a recursive lock specifying if the lock must always be
 
291
 *      silent.
170
292
 *
171
293
 *      Only the owner (thread) of a recursive lock may recurse on it.
172
294
 *
180
302
 *-----------------------------------------------------------------------------
181
303
 */
182
304
 
183
 
MXUserRecLock *
184
 
MXUser_CreateRecLock(const char *userName,  // IN:
185
 
                     MX_Rank rank)          // IN:
 
305
static MXUserRecLock *
 
306
MXUserCreateRecLock(const char *userName,  // IN:
 
307
                    MX_Rank rank,          // IN:
 
308
                    Bool beSilent)         // IN:
186
309
{
187
310
   char *properName;
188
311
   MXUserRecLock *lock;
204
327
 
205
328
   lock->vmmLock = NULL;
206
329
 
 
330
   lock->header.signature = MXUSER_REC_SIGNATURE;
207
331
   lock->header.name = properName;
208
 
   lock->header.signature = MXUSER_REC_SIGNATURE;
209
332
   lock->header.rank = rank;
 
333
   lock->header.serialNumber = MXUserAllocSerialNumber();
210
334
   lock->header.dumpFunc = MXUserDumpRecLock;
211
335
 
212
 
#if defined(MXUSER_STATS)
213
 
   lock->header.statsFunc = MXUserStatsActionRec;
214
 
   lock->header.identifier = MXUserAllocID();
 
336
   if (beSilent || !MXUserStatsEnabled()) {
 
337
      lock->header.statsFunc = NULL;
 
338
      Atomic_WritePtr(&lock->statsMem, NULL);
 
339
   } else {
 
340
      MXUser_ControlRecLock(lock, MXUSER_CONTROL_ENABLE_STATS);
 
341
   }
215
342
 
216
343
   MXUserAddToList(&lock->header);
217
 
   MXUserAcquisitionStatsSetUp(&lock->acquisitionStats);
218
 
   MXUserBasicStatsSetUp(&lock->heldStats, MXUSER_STAT_CLASS_HELD);
219
 
#endif
220
344
 
221
345
   return lock;
222
346
}
225
349
/*
226
350
 *-----------------------------------------------------------------------------
227
351
 *
 
352
 * MXUser_CreateRecLockSilent --
 
353
 *
 
354
 *      Create a recursive lock specifying if the lock must always be
 
355
 *      silent - never logging any messages. Silent locks will never
 
356
 *      produce any statistics, amongst the aspects of "silent".
 
357
 *
 
358
 *      Only the owner (thread) of a recursive lock may recurse on it.
 
359
 *
 
360
 * Results:
 
361
 *      NULL  Creation failed
 
362
 *      !NULL Creation succeeded
 
363
 *
 
364
 * Side effects:
 
365
 *      None
 
366
 *
 
367
 *-----------------------------------------------------------------------------
 
368
 */
 
369
 
 
370
MXUserRecLock *
 
371
MXUser_CreateRecLockSilent(const char *userName,  // IN:
 
372
                           MX_Rank rank)          // IN:
 
373
{
 
374
   return MXUserCreateRecLock(userName, rank, TRUE);
 
375
}
 
376
 
 
377
/*
 
378
 *-----------------------------------------------------------------------------
 
379
 *
 
380
 * MXUser_CreateRecLock --
 
381
 *
 
382
 *      Create a recursive lock.
 
383
 *
 
384
 *      Only the owner (thread) of a recursive lock may recurse on it.
 
385
 *
 
386
 * Results:
 
387
 *      NULL  Creation failed
 
388
 *      !NULL Creation succeeded
 
389
 *
 
390
 * Side effects:
 
391
 *      None
 
392
 *
 
393
 *-----------------------------------------------------------------------------
 
394
 */
 
395
 
 
396
MXUserRecLock *
 
397
MXUser_CreateRecLock(const char *userName,  // IN:
 
398
                     MX_Rank rank)          // IN:
 
399
{
 
400
   return MXUserCreateRecLock(userName, rank, FALSE);
 
401
}
 
402
 
 
403
 
 
404
/*
 
405
 *-----------------------------------------------------------------------------
 
406
 *
228
407
 * MXUser_DestroyRecLock --
229
408
 *
230
409
 *      Destroy a recursive lock.
231
410
 *
232
411
 *      When the lock is bound to a MX lock, only the MXUser "wrapper" is
233
412
 *      freed. The caller is responsible for calling MX_DestroyLockRec() on
234
 
 *      the MX lock.
 
413
 *      the MX lock before calling this routine.
235
414
 *
236
415
 * Results:
237
416
 *      Lock is destroyed. Don't use the pointer again.
246
425
MXUser_DestroyRecLock(MXUserRecLock *lock)  // IN:
247
426
{
248
427
   if (lock != NULL) {
 
428
      MXUserStats *stats;
 
429
 
249
430
      ASSERT(lock->header.signature == MXUSER_REC_SIGNATURE);
250
431
 
251
432
      if (lock->vmmLock == NULL) {
257
438
 
258
439
         MXRecLockDestroy(&lock->recursiveLock);
259
440
 
260
 
#if defined(MXUSER_STATS)
261
441
         MXUserRemoveFromList(&lock->header);
262
 
         MXUserAcquisitionStatsTearDown(&lock->acquisitionStats);
263
 
         MXUserBasicStatsTearDown(&lock->heldStats);
264
 
         MXUserHistoTearDown(Atomic_ReadPtr(&lock->acquisitionHisto));
265
 
         MXUserHistoTearDown(Atomic_ReadPtr(&lock->heldHisto));
266
 
#endif
 
442
 
 
443
         stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
444
 
 
445
         if (stats) {
 
446
            MXUserAcquisitionStatsTearDown(&stats->acquisitionStats);
 
447
            MXUserBasicStatsTearDown(&stats->heldStats);
 
448
            MXUserHistoTearDown(Atomic_ReadPtr(&stats->acquisitionHisto));
 
449
            MXUserHistoTearDown(Atomic_ReadPtr(&stats->heldHisto));
 
450
 
 
451
            free(stats);
 
452
         }
267
453
      }
268
454
 
269
455
      lock->header.signature = 0;  // just in case...
270
 
      free((void *) lock->header.name);  // avoid const warnings
 
456
      free(lock->header.name);
271
457
      lock->header.name = NULL;
272
458
      free(lock);
273
459
   }
301
487
      ASSERT(MXUserMX_LockRec);
302
488
      (*MXUserMX_LockRec)(lock->vmmLock);
303
489
   } else {
304
 
#if defined(MXUSER_STATS)
305
 
      Bool contended;
306
 
      VmTimeType begin;
307
 
#endif
 
490
      MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
491
 
308
492
      /* Rank checking is only done on the first acquisition */
309
493
      MXUserAcquisitionTracking(&lock->header, TRUE);
310
494
 
311
 
#if defined(MXUSER_STATS)
312
 
      begin = Hostinfo_SystemTimerNS();
313
 
 
314
 
      contended =
315
 
#endif
316
 
 
317
 
      MXRecLockAcquire(&lock->recursiveLock, GetReturnAddress());
318
 
 
319
 
#if defined(MXUSER_STATS)
320
 
      if (MXRecLockCount(&lock->recursiveLock) == 1) {
321
 
         MXUserHisto *histo;
322
 
         VmTimeType value = Hostinfo_SystemTimerNS() - begin;
323
 
 
324
 
         MXUserAcquisitionSample(&lock->acquisitionStats, contended, value);
325
 
 
326
 
         histo = Atomic_ReadPtr(&lock->acquisitionHisto);
327
 
 
328
 
         if (UNLIKELY(histo != NULL)) {
329
 
            MXUserHistoSample(histo, value);
 
495
      if (stats) {
 
496
         Bool contended;
 
497
         VmTimeType begin = Hostinfo_SystemTimerNS();
 
498
 
 
499
         contended = MXRecLockAcquire(&lock->recursiveLock);
 
500
 
 
501
         if (MXRecLockCount(&lock->recursiveLock) == 1) {
 
502
            MXUserHisto *histo;
 
503
            VmTimeType value = Hostinfo_SystemTimerNS() - begin;
 
504
 
 
505
            MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, contended,
 
506
                                    value);
 
507
 
 
508
            stats->holder = GetReturnAddress();
 
509
 
 
510
            histo = Atomic_ReadPtr(&stats->acquisitionHisto);
 
511
 
 
512
            if (UNLIKELY(histo != NULL)) {
 
513
               MXUserHistoSample(histo, value, stats->holder);
 
514
            }
 
515
 
 
516
            stats->holdStart = Hostinfo_SystemTimerNS();
330
517
         }
331
 
 
332
 
         lock->holdStart = Hostinfo_SystemTimerNS();
 
518
      } else {
 
519
         MXRecLockAcquire(&lock->recursiveLock);
333
520
      }
334
 
#endif
335
521
   }
336
522
}
337
523
 
361
547
      ASSERT(MXUserMX_UnlockRec);
362
548
      (*MXUserMX_UnlockRec)(lock->vmmLock);
363
549
   } else {
364
 
#if defined(MXUSER_STATS)
365
 
      if (MXRecLockCount(&lock->recursiveLock) == 1) {
366
 
         VmTimeType value = Hostinfo_SystemTimerNS() - lock->holdStart;
367
 
         MXUserHisto *histo = Atomic_ReadPtr(&lock->heldHisto);
368
 
 
369
 
         MXUserBasicStatsSample(&lock->heldStats, value);
370
 
 
371
 
         if (UNLIKELY(histo != NULL)) {
372
 
            MXUserHistoSample(histo, value);
 
550
      MXUserStats *stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
551
 
 
552
      if (stats) {
 
553
         if (MXRecLockCount(&lock->recursiveLock) == 1) {
 
554
            VmTimeType value = Hostinfo_SystemTimerNS() - stats->holdStart;
 
555
            MXUserHisto *histo = Atomic_ReadPtr(&stats->heldHisto);
 
556
 
 
557
            MXUserBasicStatsSample(&stats->heldStats, value);
 
558
 
 
559
            if (UNLIKELY(histo != NULL)) {
 
560
               MXUserHistoSample(histo, value, stats->holder);
 
561
               stats->holder = NULL;
 
562
            }
373
563
         }
374
564
      }
375
 
#endif
376
565
 
377
566
      if (!MXRecLockIsOwner(&lock->recursiveLock)) {
378
567
         uint32 lockCount = MXRecLockCount(&lock->recursiveLock);
424
613
      ASSERT(MXUserMX_TryLockRec);
425
614
      success = (*MXUserMX_TryLockRec)(lock->vmmLock);
426
615
   } else {
427
 
#if defined(MXUSER_STATS)
428
 
      VmTimeType begin;
429
 
#endif
 
616
      MXUserStats *stats;
430
617
 
431
618
      if (MXUserTryAcquireFail(lock->header.name)) {
432
619
         return FALSE;
433
620
      }
434
621
 
435
 
#if defined(MXUSER_STATS)
436
 
      begin = Hostinfo_SystemTimerNS();
437
 
#endif
438
 
 
439
 
      success = MXRecLockTryAcquire(&lock->recursiveLock, GetReturnAddress());
 
622
      success = MXRecLockTryAcquire(&lock->recursiveLock);
440
623
 
441
624
      if (success) {
442
 
#if defined(MXUSER_STATS)
443
 
         if (MXRecLockCount(&lock->recursiveLock) == 1) {
444
 
            MXUserAcquisitionSample(&lock->acquisitionStats, FALSE,
445
 
                                  Hostinfo_SystemTimerNS() - begin);
446
 
         }
447
 
#endif
448
 
 
449
625
         MXUserAcquisitionTracking(&lock->header, FALSE);
450
626
      }
 
627
 
 
628
      stats = (MXUserStats *) Atomic_ReadPtr(&lock->statsMem);
 
629
 
 
630
      if (stats) {
 
631
         MXUserAcquisitionSample(&stats->acquisitionStats, success,
 
632
                                 !success, 0ULL);
 
633
      }
451
634
   }
452
635
 
453
636
   return success;
491
674
/*
492
675
 *-----------------------------------------------------------------------------
493
676
 *
494
 
 * MXUser_ControlRecLock --
495
 
 *
496
 
 *      Perform the specified command on the specified lock.
497
 
 *
498
 
 * Results:
499
 
 *      TRUE    succeeded
500
 
 *      FALSE   failed
501
 
 *
502
 
 * Side effects:
503
 
 *      Depends on the command, no?
504
 
 *
505
 
 *-----------------------------------------------------------------------------
506
 
 */
507
 
 
508
 
Bool
509
 
MXUser_ControlRecLock(MXUserRecLock *lock,  // IN/OUT:
510
 
                      uint32 command,       // IN:
511
 
                      ...)                  // IN:
512
 
{
513
 
   Bool result;
514
 
 
515
 
   ASSERT(lock && (lock->header.signature == MXUSER_REC_SIGNATURE));
516
 
   ASSERT(lock->vmmLock == NULL);  // only unbound locks
517
 
 
518
 
   switch (command) {
519
 
#if defined(MXUSER_STATS)
520
 
   case MXUSER_CONTROL_ACQUISITION_HISTO: {
521
 
      va_list a;
522
 
      uint64 minValue;
523
 
      uint32 decades;
524
 
 
525
 
      va_start(a, command);
526
 
      minValue = va_arg(a, uint64);
527
 
      decades = va_arg(a, uint32);
528
 
      va_end(a);
529
 
 
530
 
      MXUserForceHisto(&lock->acquisitionHisto, MXUSER_STAT_CLASS_ACQUISITION,
531
 
                       minValue, decades);
532
 
 
533
 
      result = TRUE;
534
 
      break;
535
 
   }
536
 
 
537
 
   case MXUSER_CONTROL_HELD_HISTO: {
538
 
      va_list a;
539
 
      uint64 minValue;
540
 
      uint32 decades;
541
 
 
542
 
      va_start(a, command);
543
 
      minValue = va_arg(a, uint64);
544
 
      decades = va_arg(a, uint32);
545
 
      va_end(a);
546
 
 
547
 
      MXUserForceHisto(&lock->heldHisto, MXUSER_STAT_CLASS_HELD,
548
 
                       minValue, decades);
549
 
      
550
 
      result = TRUE;
551
 
      break; 
552
 
   }
553
 
#endif
554
 
 
555
 
   default:
556
 
      result = FALSE;
557
 
   }
558
 
 
559
 
   return result;
560
 
}
561
 
 
562
 
 
563
 
/*
564
 
 *-----------------------------------------------------------------------------
565
 
 *
566
677
 * MXUser_CreateSingletonRecLock --
567
678
 *
568
679
 *      Ensures that the specified backing object (Atomic_Ptr) contains a
591
702
   lock = (MXUserRecLock *) Atomic_ReadPtr(lockStorage);
592
703
 
593
704
   if (UNLIKELY(lock == NULL)) {
594
 
      MXUserRecLock *before;
595
 
 
596
 
      lock = MXUser_CreateRecLock(name, rank);
597
 
 
598
 
      before = (MXUserRecLock *) Atomic_ReadIfEqualWritePtr(lockStorage, NULL,
599
 
                                                            (void *) lock);
600
 
 
601
 
      if (before) {
602
 
         MXUser_DestroyRecLock(lock);
603
 
 
604
 
         lock = before;
 
705
      MXUserRecLock *newLock = MXUser_CreateRecLock(name, rank);
 
706
 
 
707
      lock = (MXUserRecLock *) Atomic_ReadIfEqualWritePtr(lockStorage, NULL,
 
708
                                                          (void *) newLock);
 
709
 
 
710
      if (lock) {
 
711
         MXUser_DestroyRecLock(newLock);
 
712
      } else {
 
713
         lock = (MXUserRecLock *) Atomic_ReadPtr(lockStorage);
605
714
      }
606
715
   }
607
716
 
649
758
 *      As above.
650
759
 *
651
760
 * Side effects:
652
 
 *      None.
 
761
 *      It is possible to return from this routine without the condtion
 
762
 *      variable having been signalled (spurious wake up); code accordingly!
653
763
 *
654
764
 *-----------------------------------------------------------------------------
655
765
 */
676
786
 *      blocking and is reacquired before returning from this function.
677
787
 *
678
788
 * Results:
679
 
 *      TRUE   condVar was signalled
680
 
 *      FALSE  timed out waiting for signal
 
789
 *      As above
681
790
 *
682
791
 * Side effects:
683
 
 *      None.
 
792
 *      It is possible to return from this routine without the condtion
 
793
 *      variable having been signalled (spurious wake up); code accordingly!
684
794
 *
685
795
 *-----------------------------------------------------------------------------
686
796
 */
687
797
 
688
 
Bool
 
798
void
689
799
MXUser_TimedWaitCondVarRecLock(MXUserRecLock *lock,     // IN:
690
800
                               MXUserCondVar *condVar,  // IN:
691
801
                               uint32 msecWait)         // IN:
693
803
   ASSERT(lock && (lock->header.signature == MXUSER_REC_SIGNATURE));
694
804
   ASSERT(lock->vmmLock == NULL);  // only unbound locks
695
805
 
696
 
   return MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar,
697
 
                            msecWait);
 
806
   MXUserWaitCondVar(&lock->header, &lock->recursiveLock, condVar, msecWait);
 
807
}
 
808
 
 
809
 
 
810
/*
 
811
 *-----------------------------------------------------------------------------
 
812
 *
 
813
 * MXUser_DumpRecLock --
 
814
 *
 
815
 *      Dump a recursive lock.
 
816
 *
 
817
 * Results:
 
818
 *      None.
 
819
 *
 
820
 * Side effects:
 
821
 *      None.
 
822
 *
 
823
 *-----------------------------------------------------------------------------
 
824
 */
 
825
 
 
826
void
 
827
MXUser_DumpRecLock(MXUserRecLock *lock)  // IN:
 
828
{
 
829
   ASSERT(lock && (lock->header.signature == MXUSER_REC_SIGNATURE));
 
830
 
 
831
   MXUserDumpRecLock(&lock->header);
698
832
}
699
833
 
700
834
 
794
928
 
795
929
   lock = Util_SafeCalloc(1, sizeof(*lock));
796
930
 
 
931
   lock->header.signature = MXUSER_REC_SIGNATURE;
797
932
   lock->header.name = Str_SafeAsprintf(NULL, "MX_%p", mutex);
798
 
 
799
 
   lock->header.signature = MXUSER_REC_SIGNATURE;
800
933
   lock->header.rank = rank;
 
934
   lock->header.serialNumber = MXUserAllocSerialNumber();
801
935
   lock->header.dumpFunc = NULL;
802
 
 
803
 
#if defined(MXUSER_STATS)
804
936
   lock->header.statsFunc = NULL;
805
 
   lock->header.identifier = MXUserAllocID();
806
 
#endif
 
937
 
 
938
   Atomic_WritePtr(&lock->statsMem, NULL);
807
939
 
808
940
   lock->vmmLock = mutex;
809
941
 
813
945
 
814
946
#if defined(VMX86_VMX)
815
947
#include "mutex.h"
816
 
#include "mutexRank.h"
 
948
#include "mutexRankVMX.h"
817
949
 
818
950
/*
819
951
 *----------------------------------------------------------------------------