Closed Bug 200335 Opened 21 years ago Closed 21 years ago

The zone allocator does not work on Mac OS X (Darwin).

Categories

(NSPR :: NSPR, defect)

PowerPC
macOS
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: wtc, Assigned: wtc)

Details

The zone allocator does not work on Mac OS X (Darwin).

If I set the environment variable NSPR_USE_ZONE_ALLOCATOR
to 1 and run any NSPR test (the debug build), I hit an
assertion failure:

Assertion failure: mb->s.magic == ZONE_MAGIC, at ../../../../mozilla/nsprpub/pr/
src/malloc/prmem.c:246
Abort

(This is revision 3.12 of mozilla/nsprpub/pr/src/malloc/prmem.c.)

If I run the optimized build, the test crashes with a bus
error.
The problem occurs in the first call to pr_ZoneMalloc.
It occurs in this code:

    if (zone < MEM_ZONES) {
        pthread_t me = pthread_self();
        unsigned int pool = (ptrdiff_t)me % THREAD_POOLS;
        PRUint32     wasLocked;
        mz = &zones[zone][pool];

The value of "me" is 0xa0000dec (or similar), which when cast as a ptrdiff_t
is a negative number.  ptrdiff_t is a signed type.  THREAD_POOLS is 11.
The result of the modulus operation is a negative number (-7).  

The code uses ptrdiff_t because this type is guaranteed to be the size of 
a pointer.  But it is signed.  What we need is an unsigned integer type
that is guaranteed to be the same size as a pointer.  
Casting to "unsigned ptrdiff_t" generates a "parsing error".

Substituting "unsigned long" for "ptrdiff_t" works on OSX 
(which is expected for a BSD derivative), but may not work on all 
platforms (e.g. 64-bit windows for iTanium, where IINM long is 32 bits
but pointers are 64-bits).  

Nelson, you can use PRUptrdiff.  I think size_t would also
work.

When support for the 1999 revision of Standard C is widely
available, we will be able to use the uintptr_t type, defined
in the new Standard C header file <inttypes.h>, which is an
unsigned integer type large enough to hold any data pointer.
The following change works correctly on OSX:

-        unsigned int pool = (ptrdiff_t)me % THREAD_POOLS;
+        unsigned int pool = (PRUptrdiff)me % THREAD_POOLS;

This appears to be the only modulus operation in the source file.
Do you want to commit that change?
Fix checked into the NSPR tip.  Thank you, Nelson.
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
Whiteboard: [4.3.1]
Target Milestone: --- → 4.3
Whiteboard: [4.3.1]
Target Milestone: 4.3 → 4.4
You need to log in before you can comment on or make changes to this bug.