#ifdef DEBUG DO(kreci, if(x==krec[i]){krec[i]=0; break; }) #endif SW(xt) { CS(7, DO(-2+TYPE_SEVEN_SIZE,cd(kV(x)[2+i]))) //-4 special trick: don't recurse on V members. assumes sizeof S==K==V. (don't free CONTeXT or DEPTH) } #ifdef DEBUG if(0)R 0; //for viewing K that have been over-freed #endif //assumes seven_type x->k is < PG I o=((size_t)x)&(PG-1);//file-mapped? 1: I k=sz(xt,xn), r=lsz(k); //assert file-maps have sizeof(V)==o and unpooled blocks never do (reasonable) //in 32-bit Linux: sizeof(V)==4 but file-maps have o==8 //in 64-bit Linux: sizeof(V)==8 and file-maps have o==8 if(o==8 || r>KP_MAX){ //(file-mapped or really big) do not go back into pool. I res=munmap(((V)x)-o,k+o); if(res)R UE; if(r>KP_MAX) mUsed -= (k+o); } else repool(x,r); R 0; } K ci(K x) { P(!x,0) x->c++; SW(xt)
{ #ifdef DEBUG if(a && a->c <=0 ) { er(Tried to cd() already freed item) dd(tests) dd(a) dd(a->c) dd(a->t) dd(a->n) show(a); } #endif if(!a || --a->c) R a; #ifdef DEBUG DO(kreci, if(a==krec[i]){krec[i]=0; break; }) #endif if(7==a->t){ DO(-2+TYPE_SEVEN_SIZE,cd(kV(a)[2+i]))} //-4 special trick: don't recurse on V members. assumes sizeof S==K==V. (don't free CONTEXT or DEPTH) if(0==a->t || 5==a->t) DO(a->n, cd(kK(a)[a->n-i-1])) //repool in reverse, attempt to maintain order #ifdef DEBUG if(0)R 0; //for viewing K that have been over-freed #endif //assumes seven_type a->k is < PG I o=((size_t)a)&(PG-1);//file-mapped? 1: I k=sz(a->t,a->n), r=lsz(k); //assert file-maps have sizeof(V)==o and unpooled blocks never do (reasonable) if(sizeof(V)==o || r>KP_MAX)munmap(((V)a)-o,k+o); //(file-mapped or really big) do not go back into pool. else repool(a,r); R 0; } K ci(K a){if(a)a->c++; R a;} I bp(I t) {SW(ABS(t)){CSR(1, R sizeof(I)) CSR(2, R sizeof(F)) CSR(3, R sizeof(C)) CD: R sizeof(V); } } //Default 0/+-4/5/6/7 (assumes sizeof(K)==sizeof(S)==...) I sz(I t,I n){R 3*sizeof(I)+(7==t?TYPE_SEVEN_SIZE:n)*bp(t)+(3==ABS(t));} //not recursive. assert sz() > 0: Everything gets valid block for simplified munmap/(free) Z I nearPG(I i){ I k=((size_t)i)&(PG-1);R k?i+PG-k:i;}//up 0,8,...,8,16,16,... //This is an untested idea for avoiding all that goes on in backing out of memory allocations when an error occurs inside a function before everything is done: //If you control the memory allocator one possibility is to work in "claimed" (sbreak) but "free" space and build the K data structure there. //Doing ci() or something similar on it marks the space "used". on error you do nothing and the space remains "free" (mutex)