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

« back to all changes in this revision

Viewing changes to lib/lock/ul.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:
23
23
#include "ulInt.h"
24
24
#include "ulIntShared.h"
25
25
#include "hashTable.h"
26
 
 
 
26
#include "random.h"
27
27
 
28
28
static Bool mxInPanic = FALSE;  // track when involved in a panic
29
29
 
37
37
Bool (*MXUserMX_IsLockedByCurThreadRec)(const struct MX_MutexRec *lock) = NULL;
38
38
 
39
39
 
 
40
/*
 
41
 *-----------------------------------------------------------------------------
 
42
 *
 
43
 * MXUserInternalSingleton --
 
44
 *
 
45
 *      A "singleton" function for the MXUser internal recursive lock.
 
46
 *
 
47
 *      Internal MXUser recursive locks have no statistics gathering or
 
48
 *      tracking abilities. They need to used with care and rarely.
 
49
 *
 
50
 * Results:
 
51
 *      NULL    Failure
 
52
 *      !NULL   A pointer to an initialized MXRecLock
 
53
 *
 
54
 * Side effects:
 
55
 *      Manifold.
 
56
 *
 
57
 *-----------------------------------------------------------------------------
 
58
 */
 
59
 
 
60
MXRecLock *
 
61
MXUserInternalSingleton(Atomic_Ptr *storage)  // IN:
 
62
{
 
63
   MXRecLock *lock = (MXRecLock *) Atomic_ReadPtr(storage);
 
64
 
 
65
   if (UNLIKELY(lock == NULL)) {
 
66
      MXRecLock *newLock = Util_SafeMalloc(sizeof(MXRecLock));
 
67
 
 
68
      if (MXRecLockInit(newLock)) {
 
69
         lock = (MXRecLock *) Atomic_ReadIfEqualWritePtr(storage, NULL,
 
70
                                                         (void *) newLock);
 
71
 
 
72
         if (lock) {
 
73
            MXRecLockDestroy(newLock);
 
74
            free(newLock);
 
75
         } else {
 
76
            lock = Atomic_ReadPtr(storage);
 
77
         }
 
78
      } else {
 
79
         free(newLock);
 
80
         lock = Atomic_ReadPtr(storage);  // maybe another thread succeeded
 
81
      }
 
82
   }
 
83
 
 
84
   return lock;
 
85
}
 
86
 
 
87
 
 
88
#define MXUSER_SYNDROME
 
89
#if defined(MXUSER_SYNDROME)
 
90
/*
 
91
 *-----------------------------------------------------------------------------
 
92
 *
 
93
 * MXUserSydrome --
 
94
 *
 
95
 *      Generate the syndrome bits for this MXUser library.
 
96
 *
 
97
 *      Each MXUser library has unique syndrome bits enabling the run time
 
98
 *      detection of locks created with one copy of the MXUser library and
 
99
 *      passed to another copy of the MXUser library.
 
100
 *
 
101
 *      The syndrome bits are important as they prevent incompatible versions
 
102
 *      of the MXUser library from trashing each other.
 
103
 *
 
104
 *      The bits are generated by using a source of bits that is external to
 
105
 *      a program and its libraries. This way no code or data based scheme
 
106
 *      can be spoofed or aliased.
 
107
 *
 
108
 * Results:
 
109
 *      As above
 
110
 *
 
111
 * Side effects:
 
112
 *      None
 
113
 *
 
114
 *-----------------------------------------------------------------------------
 
115
 */
 
116
 
 
117
static uint32
 
118
MXUserSyndrome(void)
 
119
{
 
120
   uint32 syndrome;
 
121
   static Atomic_uint32 syndromeMem;  // implicitly zero -- mbellon
 
122
 
 
123
   syndrome = Atomic_Read(&syndromeMem);
 
124
 
 
125
   if (syndrome == 0) {
 
126
      uint32 retries = 25;
 
127
 
 
128
      /*
 
129
       * Do not assume that the source of bits from the host OS are sane.
 
130
       * Perhaps its random bits service is not working or always returns
 
131
       * zero or something is misconfigured. Only perform a small number
 
132
       * of retries attempting to appropriate the required bits.
 
133
       */
 
134
 
 
135
      do {
 
136
         /* Only changes syndrome on success. No need to check for errors */
 
137
         Random_Crypto(sizeof syndrome, &syndrome);
 
138
 
 
139
         if (syndrome != 0) {
 
140
            break;
 
141
         }
 
142
      } while (retries--);
 
143
 
 
144
      /*
 
145
       * If the source was unable to provide the appropriate bits, switch
 
146
       * to plan B.
 
147
       */
 
148
 
 
149
      if (syndrome == 0) {
 
150
#if defined(_WIN32)
 
151
         syndrome = GetTickCount();
 
152
#else
 
153
         syndrome = time(NULL) & 0xFFFFFFFF;
 
154
#endif
 
155
      }
 
156
 
 
157
      /*
 
158
       * Protect against a total failure.
 
159
       */
 
160
 
 
161
      if (syndrome == 0) {
 
162
         syndrome++;
 
163
      }
 
164
 
 
165
      /* blind write; if racing one thread or the other will do */
 
166
      Atomic_ReadIfEqualWrite(&syndromeMem, 0, syndrome);
 
167
 
 
168
      syndrome = Atomic_Read(&syndromeMem);
 
169
   }
 
170
 
 
171
   ASSERT(syndrome);
 
172
 
 
173
   return syndrome;
 
174
}
 
175
#endif
 
176
 
 
177
 
 
178
/*
 
179
 *-----------------------------------------------------------------------------
 
180
 *
 
181
 * MXUserGetSignature --
 
182
 *
 
183
 *      Return a signature appropriate for the specified object type.
 
184
 *
 
185
 * Results:
 
186
 *      As above
 
187
 *
 
188
 * Side effects:
 
189
 *      None
 
190
 *
 
191
 *-----------------------------------------------------------------------------
 
192
 */
 
193
 
 
194
uint32
 
195
MXUserGetSignature(MXUserObjectType objectType)  // IN:
 
196
{
 
197
   uint32 signature;
 
198
 
 
199
   ASSERT((objectType >= 0) && (objectType < 16) &&
 
200
          (objectType != MXUSER_TYPE_NEVER_USE));
 
201
 
 
202
#if defined(MXUSER_SYNDROME)
 
203
   /*
 
204
    * Use a random syndrome combined with a unique bit pattern mapping
 
205
    * of objectType to bits in a nibble. The random portion of the signature
 
206
    * can be used to catch multiple copies of lib/lock that are "leaking"
 
207
    * locks between them (which may be incompatible due to internal changes).
 
208
    */
 
209
 
 
210
   signature = (MXUserSyndrome() & 0x0FFFFFFF) | (objectType << 28);
 
211
#else
 
212
   /*
 
213
    * Map the abstract objectType back to the bit patterns used in older
 
214
    * versions of lib/lock. This provides absolute compatibility with
 
215
    * these older libraries.
 
216
    */
 
217
 
 
218
   switch (objectType) {
 
219
   case MXUSER_TYPE_RW:
 
220
      signature = 0x57524B4C;
 
221
      break;
 
222
 
 
223
   case MXUSER_TYPE_REC:
 
224
      signature = 0x43524B4C;
 
225
      break;
 
226
 
 
227
   case MXUSER_TYPE_RANK:
 
228
      signature = 0x4E4B5241;
 
229
      break;
 
230
 
 
231
   case MXUSER_TYPE_EXCL:
 
232
      signature = 0x58454B4C;
 
233
      break;
 
234
 
 
235
   case MXUSER_TYPE_SEMA:
 
236
      signature = 0x414D4553;
 
237
      break;
 
238
 
 
239
   case MXUSER_TYPE_CONDVAR:
 
240
      signature = 0x444E4F43;
 
241
      break;
 
242
 
 
243
   case MXUSER_TYPE_BARRIER:
 
244
      signature = 0x52524142;
 
245
      break;
 
246
 
 
247
   default:
 
248
      Panic("%s: unknown objectType %d\n", __FUNCTION__, objectType);
 
249
   }
 
250
#endif
 
251
 
 
252
   ASSERT(signature);
 
253
 
 
254
   return signature;
 
255
}
 
256
 
 
257
 
 
258
/*
 
259
 *-----------------------------------------------------------------------------
 
260
 *
 
261
 * MXUserDumpAndPanic --
 
262
 *
 
263
 *      Dump a lock, print a message and die
 
264
 *
 
265
 * Results:
 
266
 *      A panic.
 
267
 *
 
268
 * Side effects:
 
269
 *      Manifold.
 
270
 *
 
271
 *-----------------------------------------------------------------------------
 
272
 */
 
273
 
 
274
void
 
275
MXUserDumpAndPanic(MXUserHeader *header,  // IN:
 
276
                   const char *fmt,       // IN:
 
277
                   ...)                   // IN:
 
278
{
 
279
   char *msg;
 
280
   va_list ap;
 
281
 
 
282
   ASSERT((header != NULL) && (header->dumpFunc != NULL));
 
283
 
 
284
   (*header->dumpFunc)(header);
 
285
 
 
286
   va_start(ap, fmt);
 
287
   msg = Str_SafeVasprintf(NULL, fmt, ap);
 
288
   va_end(ap);
 
289
 
 
290
   Panic("%s", msg);
 
291
}
 
292
 
 
293
 
 
294
/*
 
295
 *---------------------------------------------------------------------
 
296
 * 
 
297
 *  MXUser_SetInPanic --
 
298
 *      Notify the locking system that a panic is occurring.
 
299
 *
 
300
 *      This is the "out of the monitor" - userland - implementation. The "in
 
301
 *      the monitor" implementation lives in mutex.c.
 
302
 *
 
303
 *  Results:
 
304
 *     Set the internal "in a panic" global variable.
 
305
 *
 
306
 *  Side effects:
 
307
 *     None
 
308
 *
 
309
 *---------------------------------------------------------------------
 
310
 */
 
311
 
 
312
void
 
313
MXUser_SetInPanic(void)
 
314
{
 
315
   mxInPanic = TRUE;
 
316
}
 
317
 
 
318
 
 
319
/*
 
320
 *---------------------------------------------------------------------
 
321
 * 
 
322
 *  MXUser_InPanic --
 
323
 *      Is the caller in the midst of a panic?
 
324
 *
 
325
 *      This is the "out of the monitor" - userland - implementation. The "in
 
326
 *      the monitor" implementation lives in mutex.c.
 
327
 *
 
328
 *  Results:
 
329
 *     TRUE   Yes
 
330
 *     FALSE  No
 
331
 *
 
332
 *  Side effects:
 
333
 *     None
 
334
 *
 
335
 *---------------------------------------------------------------------
 
336
 */
 
337
 
 
338
Bool
 
339
MXUser_InPanic(void)
 
340
{
 
341
   return mxInPanic;
 
342
}
 
343
 
 
344
 
 
345
/*
 
346
 *-----------------------------------------------------------------------------
 
347
 *
 
348
 * MXUserInstallMxHooks --
 
349
 *
 
350
 *      The MX facility may notify the MXUser facility that it is place and
 
351
 *      that MXUser should check with it. This function should be called from
 
352
 *      MX_Init.
 
353
 *
 
354
 * Results:
 
355
 *      As Above.
 
356
 *
 
357
 * Side effects:
 
358
 *      None.
 
359
 *
 
360
 *-----------------------------------------------------------------------------
 
361
 */
 
362
 
 
363
void
 
364
MXUserInstallMxHooks(void (*theLockListFunc)(void),
 
365
                     MX_Rank (*theRankFunc)(void),
 
366
                     void (*theLockFunc)(struct MX_MutexRec *lock),
 
367
                     void (*theUnlockFunc)(struct MX_MutexRec *lock),
 
368
                     Bool (*theTryLockFunc)(struct MX_MutexRec *lock),
 
369
                     Bool (*theIsLockedFunc)(const struct MX_MutexRec *lock))
 
370
{
 
371
   /*
 
372
    * This function can be called more than once but the second and later
 
373
    * invocations must be attempting to install the same hook functions as
 
374
    * the first invocation.
 
375
    */
 
376
 
 
377
   if ((MXUserMxLockLister == NULL) &&
 
378
       (MXUserMxCheckRank == NULL) &&
 
379
       (MXUserMX_LockRec == NULL) &&
 
380
       (MXUserMX_UnlockRec == NULL) &&
 
381
       (MXUserMX_TryLockRec == NULL) &&
 
382
       (MXUserMX_IsLockedByCurThreadRec == NULL)) {
 
383
      MXUserMxLockLister = theLockListFunc;
 
384
      MXUserMxCheckRank = theRankFunc;
 
385
      MXUserMX_LockRec = theLockFunc;
 
386
      MXUserMX_UnlockRec = theUnlockFunc;
 
387
      MXUserMX_TryLockRec = theTryLockFunc;
 
388
      MXUserMX_IsLockedByCurThreadRec = theIsLockedFunc;
 
389
   } else {
 
390
      ASSERT((MXUserMxLockLister == theLockListFunc) &&
 
391
             (MXUserMxCheckRank == theRankFunc) &&
 
392
             (MXUserMX_LockRec == theLockFunc) &&
 
393
             (MXUserMX_UnlockRec == theUnlockFunc) &&
 
394
             (MXUserMX_TryLockRec == theTryLockFunc) &&
 
395
             (MXUserMX_IsLockedByCurThreadRec == theIsLockedFunc)
 
396
            );
 
397
   }
 
398
}
 
399
 
40
400
#if defined(MXUSER_DEBUG)
41
401
#define MXUSER_MAX_LOCKS_PER_THREAD (2 * MXUSER_MAX_REC_DEPTH)
42
402
 
43
 
typedef struct {
44
 
   uint32         locksHeld;
45
 
   MXUserHeader  *lockArray[MXUSER_MAX_LOCKS_PER_THREAD];
 
403
typedef struct MXUserPerThread {
 
404
   struct MXUserPerThread  *next;
 
405
   uint32                   locksHeld;
 
406
   MXUserHeader            *lockArray[MXUSER_MAX_LOCKS_PER_THREAD];
46
407
} MXUserPerThread;
47
408
 
 
409
static Atomic_Ptr perThreadLockMem;
 
410
static MXUserPerThread *perThreadFreeList = NULL;
 
411
 
48
412
static Atomic_Ptr hashTableMem;
49
413
 
50
414
 
51
415
/*
52
416
 *-----------------------------------------------------------------------------
53
417
 *
 
418
 * MXUserAllocPerThread --
 
419
 *
 
420
 *     Allocate a perThread structure.
 
421
 *
 
422
 *     Memory is allocated for the specified thread as necessary. Use a
 
423
 *     victim cache in front of malloc to provide a slight performance
 
424
 *     advantage. The lock here is equivalent to the lock buried inside
 
425
 *     malloc but no complex calculations are necessary to perform an
 
426
 *     allocation most of the time.
 
427
 *
 
428
 *     The maximum size of the list will be roughly the maximum number of
 
429
 *     threads having taken locks at the same time - a bounded number less
 
430
 *     than or equal to the maximum of threads created.
 
431
 *
 
432
 * Results:
 
433
 *     As above.
 
434
 *
 
435
 * Side effects:
 
436
 *      Memory may be allocated.
 
437
 *
 
438
 *-----------------------------------------------------------------------------
 
439
 */
 
440
 
 
441
static MXUserPerThread *
 
442
MXUserAllocPerThread(void)
 
443
{
 
444
   MXUserPerThread *perThread;
 
445
   MXRecLock *perThreadLock = MXUserInternalSingleton(&perThreadLockMem);
 
446
 
 
447
   ASSERT(perThreadLock);
 
448
 
 
449
   MXRecLockAcquire(perThreadLock);
 
450
 
 
451
   if (perThreadFreeList == NULL) {
 
452
      perThread = Util_SafeMalloc(sizeof *perThread);
 
453
   } else {
 
454
      perThread = perThreadFreeList;
 
455
      perThreadFreeList = perThread->next;
 
456
   }
 
457
 
 
458
   MXRecLockRelease(perThreadLock);
 
459
 
 
460
   ASSERT(perThread);
 
461
 
 
462
   memset(perThread, 0, sizeof *perThread);  // ensure all zeros
 
463
 
 
464
   return perThread;
 
465
}
 
466
 
 
467
 
 
468
/*
 
469
 *-----------------------------------------------------------------------------
 
470
 *
 
471
 * MXUserFreePerThread --
 
472
 *
 
473
 *     Free a perThread structure.
 
474
 *
 
475
 *     The structure is placed on the free list -- for "later".
 
476
 *
 
477
 * Results:
 
478
 *     As above.
 
479
 *
 
480
 * Side effects:
 
481
 *      None
 
482
 *
 
483
 *-----------------------------------------------------------------------------
 
484
 */
 
485
 
 
486
static void
 
487
MXUserFreePerThread(MXUserPerThread *perThread)  // IN:
 
488
{
 
489
   MXRecLock *perThreadLock;
 
490
 
 
491
   ASSERT(perThread);
 
492
   ASSERT(perThread->next == NULL);
 
493
 
 
494
   perThreadLock = MXUserInternalSingleton(&perThreadLockMem);
 
495
   ASSERT(perThreadLock);
 
496
 
 
497
   MXRecLockAcquire(perThreadLock);
 
498
   perThread->next = perThreadFreeList;
 
499
   perThreadFreeList = perThread;
 
500
   MXRecLockRelease(perThreadLock);
 
501
}
 
502
 
 
503
 
 
504
/*
 
505
 *-----------------------------------------------------------------------------
 
506
 *
54
507
 * MXUserGetPerThread --
55
508
 *
56
509
 *      Return a pointer to the per thread data for the specified thread.
60
513
 *      lock and need to record data in the perThread.
61
514
 *
62
515
 * Results:
63
 
 *      NULL   mayAlloc was FALSE and the thread doesn't have a perThread (yet)
 
516
 *      NULL   mayAlloc was FALSE and the thread doesn't have a perThread
64
517
 *     !NULL   the perThread of the specified thread
65
518
 *
66
519
 * Side effects:
70
523
 */
71
524
 
72
525
static MXUserPerThread *
73
 
MXUserGetPerThread(void *tid,      // IN: native thread ID
74
 
                   Bool mayAlloc)  // IN: alloc perThread if not present?
 
526
MXUserGetPerThread(Bool mayAlloc)  // IN: alloc perThread if not present?
75
527
{
76
528
   HashTable *hash;
77
 
   MXUserPerThread *perThread;
 
529
   MXUserPerThread *perThread = NULL;
 
530
   void *tid = MXUserCastedThreadID();
78
531
 
79
532
   hash = HashTable_AllocOnce(&hashTableMem, 1024,
80
533
                              HASH_INT_KEY | HASH_FLAG_ATOMIC, NULL);
81
534
 
82
 
   perThread = NULL;
83
 
 
84
535
   if (!HashTable_Lookup(hash, tid, (void **) &perThread)) {
85
536
      /* No entry for this tid was found, allocate one? */
86
537
 
87
538
      if (mayAlloc) {
88
 
         MXUserPerThread *newEntry = Util_SafeCalloc(1,
89
 
                                                     sizeof(MXUserPerThread));
 
539
         MXUserPerThread *newEntry = MXUserAllocPerThread();
90
540
 
91
541
         /*
92
542
          * Attempt to (racey) insert a perThread on behalf of the specified
98
548
         ASSERT(perThread);
99
549
 
100
550
         if (perThread != newEntry) {
101
 
            free(newEntry);
 
551
            MXUserFreePerThread(newEntry);
102
552
         }
103
553
      } else {
104
554
         perThread = NULL;
130
580
void
131
581
MXUserListLocks(void)
132
582
{
133
 
   MXUserPerThread *perThread = MXUserGetPerThread(MXUserGetNativeTID(),
134
 
                                                   FALSE);
 
583
   MXUserPerThread *perThread = MXUserGetPerThread(FALSE);
135
584
 
136
585
   if (perThread != NULL) {
137
586
      uint32 i;
139
588
      for (i = 0; i < perThread->locksHeld; i++) {
140
589
         MXUserHeader *hdr = perThread->lockArray[i];
141
590
 
142
 
         Warning("\tMXUser lock %s (@%p) rank 0x%x\n", hdr->name, hdr,
 
591
         Warning("\tMXUser lock %s (@0x%p) rank 0x%x\n", hdr->name, hdr,
143
592
                 hdr->rank);
144
593
      }
145
594
   }
166
615
Bool
167
616
MXUser_IsCurThreadHoldingLocks(void)
168
617
{
169
 
   MXUserPerThread *perThread = MXUserGetPerThread(MXUserGetNativeTID(),
170
 
                                                   FALSE);
 
618
   MXUserPerThread *perThread = MXUserGetPerThread(FALSE);
171
619
 
172
620
   return (perThread == NULL) ? FALSE : (perThread->locksHeld != 0);
173
621
}
189
637
 *-----------------------------------------------------------------------------
190
638
 */
191
639
 
192
 
MX_Rank
 
640
static MX_Rank
193
641
MXUserThreadRank(MXUserPerThread *perThread,  // IN:
194
642
                 MXUserHeader *header,        // IN:
195
643
                 Bool *firstUse)              // OUT:
243
691
MXUserCurrentRank(void)
244
692
{
245
693
   MX_Rank maxRank;
246
 
   MXUserPerThread *perThread; 
247
 
 
248
 
   perThread = MXUserGetPerThread(MXUserGetNativeTID(), FALSE);
 
694
   MXUserPerThread *perThread = MXUserGetPerThread(FALSE);
249
695
 
250
696
   if (perThread == NULL) {
251
697
      maxRank = RANK_UNRANKED;
278
724
MXUserAcquisitionTracking(MXUserHeader *header,  // IN:
279
725
                          Bool checkRank)        // IN:
280
726
{
281
 
   MXUserPerThread *perThread = MXUserGetPerThread(MXUserGetNativeTID(), TRUE);
 
727
   MXUserPerThread *perThread = MXUserGetPerThread(TRUE);
282
728
 
283
729
   ASSERT_NOT_IMPLEMENTED(perThread->locksHeld < MXUSER_MAX_LOCKS_PER_THREAD);
284
730
 
357
803
{
358
804
   uint32 i;
359
805
   uint32 lastEntry;
360
 
   void *tid = MXUserGetNativeTID();
361
 
   MXUserPerThread *perThread = MXUserGetPerThread(tid, FALSE);
 
806
   MXUserPerThread *perThread = MXUserGetPerThread(FALSE);
362
807
 
363
808
   /* MXUserAcquisitionTracking should have already created a perThread */
364
809
   if (UNLIKELY(perThread == NULL)) {
365
 
      MXUserDumpAndPanic(header, "%s: perThread not found! (thread %p)\n",
366
 
                         __FUNCTION__, tid);
 
810
      MXUserDumpAndPanic(header, "%s: perThread not found! (thread 0x%p)\n",
 
811
                         __FUNCTION__, MXUserCastedThreadID());
367
812
   }
368
813
 
369
814
   /* Search the perThread for the argument lock */
375
820
 
376
821
   /* The argument lock had better be in the perThread */
377
822
   if (UNLIKELY(i >= perThread->locksHeld)) {
378
 
      MXUserDumpAndPanic(header, "%s: lock not found! (thread %p; count %u)\n",
379
 
                         __FUNCTION__, tid, perThread->locksHeld);
 
823
      MXUserDumpAndPanic(header,
 
824
                         "%s: lock not found! (thread 0x%p; count %u)\n",
 
825
                         __FUNCTION__, MXUserCastedThreadID(),
 
826
                         perThread->locksHeld);
380
827
   }
381
828
 
382
829
   /* Remove the argument lock from the perThread */
415
862
{
416
863
   MXUserTryAcquireForceFail = func;
417
864
}
 
865
 
 
866
 
 
867
/*
 
868
 *-----------------------------------------------------------------------------
 
869
 *
 
870
 * MXUserValidateHeader --
 
871
 *
 
872
 *      Validate an MXUser object header
 
873
 *
 
874
 * Results:
 
875
 *      Return  All is well
 
876
 *      Panic   All is NOT well
 
877
 *
 
878
 * Side effects:
 
879
 *      Always entertaining...
 
880
 *
 
881
 *-----------------------------------------------------------------------------
 
882
 */
 
883
 
 
884
void
 
885
MXUserValidateHeader(MXUserHeader *header,         // IN:
 
886
                     MXUserObjectType objectType)  // IN:
 
887
{
 
888
   uint32 expected = MXUserGetSignature(objectType);
 
889
 
 
890
   if (header->signature != expected) {
 
891
      MXUserDumpAndPanic(header,
 
892
                        "%s: signature failure! expected 0x%X observed 0x%X\n",
 
893
                         __FUNCTION__, expected, header->signature);
 
894
   }
 
895
 
 
896
   if (header->serialNumber == 0) {
 
897
      MXUserDumpAndPanic(header, "%s: Invalid serial number!", __FUNCTION__);
 
898
   }
 
899
}
418
900
#endif
419
 
 
420
 
 
421
 
/*
422
 
 *-----------------------------------------------------------------------------
423
 
 *
424
 
 * MXUserInternalSingleton --
425
 
 *
426
 
 *      A "singleton" function for the MXUser internal recursive lock.
427
 
 *
428
 
 *      Internal MXUser recursive locks have no statistics gathering or
429
 
 *      tracking abilities. They need to used with care and rarely.
430
 
 *
431
 
 * Results:
432
 
 *      NULL    Failure
433
 
 *      !NULL   A pointer to an initialized MXRecLock
434
 
 *
435
 
 * Side effects:
436
 
 *      Manifold.
437
 
 *
438
 
 *-----------------------------------------------------------------------------
439
 
 */
440
 
 
441
 
MXRecLock *
442
 
MXUserInternalSingleton(Atomic_Ptr *storage)  // IN:
443
 
{
444
 
   MXRecLock *lock = (MXRecLock *) Atomic_ReadPtr(storage);
445
 
 
446
 
   if (UNLIKELY(lock == NULL)) {
447
 
      MXRecLock *newLock = Util_SafeMalloc(sizeof(MXRecLock));
448
 
 
449
 
      if (MXRecLockInit(newLock)) {
450
 
         lock = (MXRecLock *) Atomic_ReadIfEqualWritePtr(storage, NULL,
451
 
                                                         (void *) newLock);
452
 
 
453
 
         if (lock) {
454
 
            MXRecLockDestroy(newLock);
455
 
            free(newLock);
456
 
         } else {
457
 
            lock = Atomic_ReadPtr(storage);
458
 
         }
459
 
      } else {
460
 
         free(newLock);
461
 
         lock = Atomic_ReadPtr(storage);  // maybe another thread succeeded
462
 
      }
463
 
   }
464
 
 
465
 
   return lock;
466
 
}
467
 
 
468
 
 
469
 
/*
470
 
 *-----------------------------------------------------------------------------
471
 
 *
472
 
 * MXUserDumpAndPanic --
473
 
 *
474
 
 *      Dump a lock, print a message and die
475
 
 *
476
 
 * Results:
477
 
 *      A panic.
478
 
 *
479
 
 * Side effects:
480
 
 *      Manifold.
481
 
 *
482
 
 *-----------------------------------------------------------------------------
483
 
 */
484
 
 
485
 
void
486
 
MXUserDumpAndPanic(MXUserHeader *header,  // IN:
487
 
                   const char *fmt,       // IN:
488
 
                   ...)                   // IN:
489
 
{
490
 
   char *msg;
491
 
   va_list ap;
492
 
 
493
 
   ASSERT((header != NULL) && (header->dumpFunc != NULL));
494
 
 
495
 
   (*header->dumpFunc)(header);
496
 
 
497
 
   va_start(ap, fmt);
498
 
   msg = Str_SafeVasprintf(NULL, fmt, ap);
499
 
   va_end(ap);
500
 
 
501
 
   Panic("%s", msg);
502
 
}
503
 
 
504
 
 
505
 
/*
506
 
 *---------------------------------------------------------------------
507
 
 * 
508
 
 *  MXUser_SetInPanic --
509
 
 *      Notify the locking system that a panic is occurring.
510
 
 *
511
 
 *      This is the "out of the monitor" - userland - implementation. The "in
512
 
 *      the monitor" implementation lives in mutex.c.
513
 
 *
514
 
 *  Results:
515
 
 *     Set the internal "in a panic" global variable.
516
 
 *
517
 
 *  Side effects:
518
 
 *     None
519
 
 *
520
 
 *---------------------------------------------------------------------
521
 
 */
522
 
 
523
 
void
524
 
MXUser_SetInPanic(void)
525
 
{
526
 
   mxInPanic = TRUE;
527
 
}
528
 
 
529
 
 
530
 
/*
531
 
 *---------------------------------------------------------------------
532
 
 * 
533
 
 *  MXUser_InPanic --
534
 
 *      Is the caller in the midst of a panic?
535
 
 *
536
 
 *      This is the "out of the monitor" - userland - implementation. The "in
537
 
 *      the monitor" implementation lives in mutex.c.
538
 
 *
539
 
 *  Results:
540
 
 *     TRUE   Yes
541
 
 *     FALSE  No
542
 
 *
543
 
 *  Side effects:
544
 
 *     None
545
 
 *
546
 
 *---------------------------------------------------------------------
547
 
 */
548
 
 
549
 
Bool
550
 
MXUser_InPanic(void)
551
 
{
552
 
   return mxInPanic;
553
 
}
554
 
 
555
 
 
556
 
/*
557
 
 *-----------------------------------------------------------------------------
558
 
 *
559
 
 * MXUserInstallMxHooks --
560
 
 *
561
 
 *      The MX facility may notify the MXUser facility that it is place and
562
 
 *      that MXUser should check with it. This function should be called from
563
 
 *      MX_Init.
564
 
 *
565
 
 * Results:
566
 
 *      As Above.
567
 
 *
568
 
 * Side effects:
569
 
 *      None.
570
 
 *
571
 
 *-----------------------------------------------------------------------------
572
 
 */
573
 
 
574
 
void
575
 
MXUserInstallMxHooks(void (*theLockListFunc)(void),
576
 
                     MX_Rank (*theRankFunc)(void),
577
 
                     void (*theLockFunc)(struct MX_MutexRec *lock),
578
 
                     void (*theUnlockFunc)(struct MX_MutexRec *lock),
579
 
                     Bool (*theTryLockFunc)(struct MX_MutexRec *lock),
580
 
                     Bool (*theIsLockedFunc)(const struct MX_MutexRec *lock))
581
 
{
582
 
   /*
583
 
    * This function can be called more than once but the second and later
584
 
    * invocations must be attempting to install the same hook functions as
585
 
    * the first invocation.
586
 
    */
587
 
 
588
 
   if ((MXUserMxLockLister == NULL) &&
589
 
       (MXUserMxCheckRank == NULL) &&
590
 
       (MXUserMX_LockRec == NULL) &&
591
 
       (MXUserMX_UnlockRec == NULL) &&
592
 
       (MXUserMX_TryLockRec == NULL) &&
593
 
       (MXUserMX_IsLockedByCurThreadRec == NULL)) {
594
 
      MXUserMxLockLister = theLockListFunc;
595
 
      MXUserMxCheckRank = theRankFunc;
596
 
      MXUserMX_LockRec = theLockFunc;
597
 
      MXUserMX_UnlockRec = theUnlockFunc;
598
 
      MXUserMX_TryLockRec = theTryLockFunc;
599
 
      MXUserMX_IsLockedByCurThreadRec = theIsLockedFunc;
600
 
   } else {
601
 
      ASSERT((MXUserMxLockLister == theLockListFunc) &&
602
 
             (MXUserMxCheckRank == theRankFunc) &&
603
 
             (MXUserMX_LockRec == theLockFunc) &&
604
 
             (MXUserMX_UnlockRec == theUnlockFunc) &&
605
 
             (MXUserMX_TryLockRec == theTryLockFunc) &&
606
 
             (MXUserMX_IsLockedByCurThreadRec == theIsLockedFunc)
607
 
            );
608
 
   }
609
 
}