Closed
Bug 41381
Opened 24 years ago
Closed 24 years ago
JSArena arena_freelist thread safety problems
Categories
(Core :: JavaScript Engine, defect, P1)
Core
JavaScript Engine
Tracking
()
VERIFIED
FIXED
M17
People
(Reporter: brendan, Assigned: brendan)
References
(Blocks 1 open bug, )
Details
(Keywords: js1.5)
Attachments
(10 files)
1.58 KB,
patch
|
Details | Diff | Splinter Review | |
4.08 KB,
patch
|
Details | Diff | Splinter Review | |
5.72 KB,
patch
|
Details | Diff | Splinter Review | |
5.73 KB,
patch
|
Details | Diff | Splinter Review | |
5.73 KB,
patch
|
Details | Diff | Splinter Review | |
5.81 KB,
patch
|
Details | Diff | Splinter Review | |
7.33 KB,
patch
|
Details | Diff | Splinter Review | |
7.59 KB,
patch
|
Details | Diff | Splinter Review | |
1.05 KB,
patch
|
Details | Diff | Splinter Review | |
1.06 KB,
patch
|
Details | Diff | Splinter Review |
Where do I start? Assuming addresses won't be replayed by malloc across a compare and swap is one biggie. Is there any "lock-free" way to maintain this linked list? I'm beginning to suspect not. /be
Assignee | ||
Comment 1•24 years ago
|
||
Mine all mine. /be
Comment 2•24 years ago
|
||
I remember we fixed this in NSPR by adding a lock around arena_freelist. Is that not thread safe, or are you going after a lock-free solution? On Alpha and PowerPC (and MIPS too, I think), you can use load-locked and store-conditional, which don't have the "ABA" problem of compare-and-swap. Unfortunately Intel x86 and Sparc only have compare-and-swap.
Assignee | ||
Comment 3•24 years ago
|
||
I was hoping for lock-free, but a lock will do. It should not be contentious, either (my best guess), but we'll have to measure to be sure. JS uses arenas for compiler temporaries and for runtime stacks. But it uses large enough sizes that I believe it won't be allocating and freeing frequently. /be
Assignee | ||
Updated•24 years ago
|
Priority: P3 → P1
Assignee | ||
Comment 5•24 years ago
|
||
Assignee | ||
Comment 6•24 years ago
|
||
Assignee | ||
Comment 7•24 years ago
|
||
Comment 8•24 years ago
|
||
I reviewed the "final patch" (attachment id=11271). Note that I only reviewed the portion related to arena_freelist_lock. 1. In jsarena.c, function JS_ArenaShutDown has two problems. First, arena_freelist is apparently a typo for arena_freelist_lock. Second, arena_freelist_lock is defined only if JS_THREADSAFE is defined, so all this code should be ifdef'd with JS_THREADSAFE. 2. jsarena.h: just wondering why you add a new function JS_ArenaShutDown rather than just destroying arena_freelist_lock in JS_ArenaFinish.
Assignee | ||
Comment 9•24 years ago
|
||
Thanks, wtc. Re: 1 -- augh! I thought I had built this code before attaching the patch. I think I built only the JS shell, which is !JS_THREADSAFE, so the JS_DESTROY_LOCK macro does nothing and there is no compile-time error. Re: 2, the problem I face with how this old code is used in JS is this: JS_ArenaFinish is called often, via JS_GC (js_ForceGC). It wants to free all arenas cached on the freelist. Maybe it should be called JS_FlushArenaFreeList or some such. There is no JS_ArenaStartUp or JS_ArenaShutDown code in the current top of trunk, however. Per-process init has been implicit, and can continue to be so long as the first thread to call JS_InitArenaPool does not race with any other thread. So in order to minimize changes, I'm keeping per-process init (let's call it "StartUp") implicit. But I can't destroy the arena_freelit_lock in JS_ArenaFinish, without opening a race to recreate the lock. Besides, it doesn't hurt to keep that lock around while JS is embedded. But we must free that lock at "ShutDown" time, hence the new JS_ArenaShutDown. Thanks again for your comments, keep them coming if you have more. New patch coming up. /be
Assignee | ||
Comment 10•24 years ago
|
||
Assignee | ||
Comment 11•24 years ago
|
||
Comment 12•24 years ago
|
||
I reviewed patch id=11308. I found that we can write JS_ArenaFinish like this to make the critical section shorter: JS_PUBLIC_API(void) JS_ArenaFinish() { JSArena *a, *next; JS_ACQUIRE_LOCK(arena_freelist_lock); a = arena_freelist; arena_freelist = NULL; JS_RELEASE_LOCK(arena_freelist_lock); for ( ; a; a = next) { next = a->next; free(a); } } You may want to replace the for loop by a while loop depending on your taste.
Assignee | ||
Comment 13•24 years ago
|
||
Assignee | ||
Comment 14•24 years ago
|
||
Assignee | ||
Comment 15•24 years ago
|
||
I filed bug 45343 on plarena.[ch] in NSPR, for inheriting similar bugs from the old NSPR1 code. /be
Assignee | ||
Comment 16•24 years ago
|
||
Last (must be final?) patch checked in. Thanks especially to troy and wtc. /be
Assignee | ||
Comment 17•24 years ago
|
||
That crazy for loop in JS_ArenaAllocate got me: I tried to break out of it early when inverting the if (a->next) {...;continue;} clause and what followed, which fails to update pool->current = a. Bad things ensue. Ultimate Mega Turbo patch coming up. /be
Assignee | ||
Comment 18•24 years ago
|
||
Assignee | ||
Comment 19•24 years ago
|
||
Fix checked in. /be
Status: ASSIGNED → RESOLVED
Closed: 24 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 20•24 years ago
|
||
There's a subtle bug in the jsarena.c change that can bust the JS GC. Patch for that regression coming up. /be
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Assignee | ||
Comment 21•24 years ago
|
||
Adding jband, who ran into the regression in xpcshell. /be
Status: REOPENED → ASSIGNED
Assignee | ||
Comment 22•24 years ago
|
||
Assignee | ||
Comment 23•24 years ago
|
||
Looking for r= here, quick, before too many people are hosed. /be
Assignee | ||
Comment 24•24 years ago
|
||
Comment 25•24 years ago
|
||
r=jband@netscape.com
Assignee | ||
Comment 26•24 years ago
|
||
Jband tested and reviewed, I'm in. Shoot me now! /be
Status: ASSIGNED → RESOLVED
Closed: 24 years ago → 24 years ago
Comment 28•24 years ago
|
||
marking fixed
Status: REOPENED → RESOLVED
Closed: 24 years ago → 24 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•