On 2009-12-17 15:39 PST, Nelson B Bolyard wrote: > On 2009-12-17 13:39 PST, Konstantin Andreev wrote:
>> Hmm... interesting. Do I understand right, "arena marks" are like >> transaction boundaries for memory allocations ? May I consider the >> equivalence: >> >> PORT_ArenaMark ~~ begin transaction >> PORT_ArenaUnmark ~~ commit transaction >> PORT_ArenaRelease ~~ rollback transaction > > That's a reasonable first approximation, yes. There were a number of errors of fact in my previous write-up about ArenaPools. This write-up below attempts to correct them all. ArenaPools are like heaps. The memory in them consists of large blocks, called arenas, which are allocated from the/a system heap. Inside an ArenaPool, the arenas are organized as if they were in a stack. Newly allocated arenas are "pushed" on that stack. When you attempt to allocate memory from an ArenaPool, the code first looks to see if there is enough unused space in the top arena on the stack to satisfy your request, and if so, your request is satisfied from that arena. Otherwise, a new arena is allocated (or taken from NSPR's list of freed arenas) and pushed on to the stack. The new arena is always big enough to satisfy the request, and is also at least a minimum size that is established at the time that the ArenaPool is created. The ArenaMark function returns the address of a marker in the arena at the top of the arena stack. It is the address of the place in the arena on the top of the arena stack from which the next block of memory will be allocated. Each ArenaPool has its own separate stack, and hence marks are only relevant to the ArenaPool from which they are gotten. Marks may be nested. That is, a thread can get a mark, and then get another mark. It is intended that all the marks in an ArenaPool may only be owned by a single thread. In DEBUG builds, this is enforced. In non-DEBUG builds, it is not. In DEBUG builds, when a thread gets a mark from an ArenaPool, no other thread may acquire a mark in that ArenaPool while that mark exists, that is, until that mark is unmarked or released. Therefore, it is important that every mark be unmarked or released when the creating thread has no further need for exclusive ownership of the right to manage the ArenaPool. The ArenaUnmark function discards the ArenaMark at the address given, and all marks nested inside that mark (that is, acquired from that same ArenaPool while that mark existed). It is an error for a thread other than the mark's creator to try to unmark it. When a thread has unmarked all its marks from an ArenaPool, then another thread is able to set marks in that ArenaPool. ArenaUnmark does not deallocate (or "pop") any memory allocated from the ArenaPool since the mark was created. ArenaRelease "pops" the stack back to the mark, deallocating all the memory allocated from the arenas in the ArenaPool since that mark was created, and removing any arenas from the ArenaPool that have no remaining active allocations when that is done. It implicitly releases any marks nested inside the mark being explicitly released. It is the only operation, other than destroying the ArenaPool, that potentially reduces the number of arenas on the stack. Otherwise, the stack grows until the ArenaPool is destroyed, at which point all the arenas are freed or returned to a "free arena list", depending on their sizes. -- dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto