Last Comment Bug 200335 - The zone allocator does not work on Mac OS X (Darwin).
: The zone allocator does not work on Mac OS X (Darwin).
Product: NSPR
Classification: Components
Component: NSPR (show other bugs)
: 4.3
: PowerPC Mac OS X
-- normal (vote)
: 4.4
Assigned To: Wan-Teh Chang
: Wan-Teh Chang
Depends on:
  Show dependency treegraph
Reported: 2003-04-02 11:01 PST by Wan-Teh Chang
Modified: 2003-11-26 16:30 PST (History)
1 user (show)
See Also:
Crash Signature:
QA Whiteboard:
Iteration: ---
Points: ---


Description User image Wan-Teh Chang 2003-04-02 11:01:00 PST
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/

(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
Comment 1 User image Nelson Bolyard (seldom reads bugmail) 2003-04-09 03:20:00 PDT
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.  
Comment 2 User image Nelson Bolyard (seldom reads bugmail) 2003-04-09 03:35:02 PDT
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).  

Comment 3 User image Wan-Teh Chang 2003-04-09 07:32:38 PDT
Nelson, you can use PRUptrdiff.  I think size_t would also

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.
Comment 4 User image Nelson Bolyard (seldom reads bugmail) 2003-04-10 14:54:11 PDT
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?
Comment 5 User image Wan-Teh Chang 2003-04-10 20:39:40 PDT
Fix checked into the NSPR tip.  Thank you, Nelson.

Note You need to log in before you can comment on or make changes to this bug.