Changeset 3457 for trunk/src/kash/memalloc.c
- Timestamp:
- Sep 14, 2020, 7:34:28 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kash/memalloc.c
r3456 r3457 42 42 43 43 #include <stdlib.h> 44 #include <stddef.h> 44 45 #include <assert.h> 45 46 … … 183 184 mark->stacknleft = psh->stacknleft; 184 185 mark->marknext = psh->markp; 186 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 187 mark->pstacksize = psh->pstacksize; 188 #endif 185 189 psh->markp = mark; 186 190 } … … 201 205 psh->stacknxt = mark->stacknxt; 202 206 psh->stacknleft = mark->stacknleft; 207 208 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 209 assert(mark->pstacksize <= psh->pstacksize); 210 while (mark->pstacksize < psh->pstacksize) { 211 unsigned idx = --psh->pstacksize; 212 pstack_block *psk = psh->pstack[idx]; 213 psh->pstack[idx] = NULL; 214 if (psh->curpstack == psk) 215 psh->curpstack = idx > 0 ? psh->pstack[idx - 1] : NULL; 216 pstackrelease(psh, psk); 217 } 218 219 # ifndef NDEBUG 220 if (psh->curpstack) { 221 unsigned i; 222 for (i = 0; i < psh->pstacksize; i++) 223 if (psh->curpstack == psh->pstack[i]) 224 break; 225 assert(i < psh->pstacksize); 226 } 227 # endif 228 #endif 203 229 INTON; 204 230 } … … 354 380 * Parser stack allocator. 355 381 */ 382 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 383 384 unsigned pstackretain(pstack_block *pst) 385 { 386 unsigned refs = sh_atomic_inc(&pst->refs); 387 assert(refs > 1); 388 assert(refs < 256 /* bogus, but useful */); 389 return refs; 390 } 391 392 unsigned pstackrelease(shinstance *psh, pstack_block *pst) 393 { 394 unsigned refs; 395 if (pst) { 396 refs = sh_atomic_dec(&pst->refs); 397 if (refs == 0) { 398 shinstance * const psh = shthread_get_shell(); 399 struct stack_block *top; 400 while ((top = pst->top) != &pst->first) 401 { 402 pst->top = top->prev; 403 assert(pst->top); 404 top->prev = NULL; 405 sh_free(psh, top); 406 } 407 pst->nextbyte = NULL; 408 pst->top = NULL; 409 sh_free(psh, pst); 410 } 411 } else 412 refs = 0; 413 return refs; 414 } 415 416 pstack_block *pstackpush(shinstance *psh) 417 { 418 size_t const blocksize = offsetof(pstack_block, first.space) + MINSIZE; 419 pstack_block *pst; 420 unsigned i; 421 422 INTOFF; 423 424 /* 425 * Allocate and initialize it. 426 */ 427 pst = (pstack_block *)ckmalloc(psh, blocksize); 428 pst->nextbyte = &pst->first.space[0]; 429 pst->avail = blocksize - offsetof(pstack_block, first.space); 430 pst->topsize = blocksize - offsetof(pstack_block, first.space); 431 pst->strleft = 0; 432 pst->top = &pst->first; 433 pst->allocations = 0; 434 pst->bytesalloced = 0; 435 pst->nodesalloced = 0; 436 pst->entriesalloced = 0; 437 pst->strbytesalloced = 0; 438 pst->blocks = 0; 439 pst->fragmentation = 0; 440 pst->refs = 1; 441 pst->padding = 42; 442 pst->first.prev = NULL; 443 444 /* 445 * Push it onto the stack. 446 */ 447 i = psh->pstacksize; 448 if (i + 1 < psh->pstackalloced) { 449 /* likely, except for the first time */ 450 } else { 451 psh->pstack = (pstack_block **)ckrealloc(psh, psh->pstack, sizeof(psh->pstack[0]) * (i + 32)); 452 memset(&psh->pstack[i], 0, sizeof(psh->pstack[0]) * 32); 453 } 454 psh->pstack[i] = pst; 455 psh->pstacksize = i + 1; 456 psh->curpstack = pst; 457 458 INTON; 459 return pst; 460 } 461 462 /** 463 * Allocates and pushes a new block onto the stack, min payload size @a nbytes. 464 */ 465 static void pstallocnewblock(shinstance *psh, pstack_block *pst, size_t nbytes) 466 { 467 /* Allocate a new stack node. */ 468 struct stack_block *sp; 469 size_t const blocksize = nbytes <= MINSIZE 470 ? offsetof(struct stack_block, space) + MINSIZE 471 : K_ALIGN_Z(nbytes + offsetof(struct stack_block, space), 1024); 472 473 INTOFF; 474 sp = ckmalloc(psh, blocksize); 475 sp->prev = pst->top; 476 pst->fragmentation += pst->avail; 477 pst->topsize = blocksize - offsetof(struct stack_block, space); 478 pst->avail = blocksize - offsetof(struct stack_block, space); 479 pst->nextbyte = sp->space; 480 pst->top = sp; 481 pst->blocks += 1; 482 INTON; 483 } 484 485 /** 486 * Tries to grow the current stack block to hold a minimum of @a nbytes, 487 * will allocate a new block and copy over pending string bytes if that's not 488 * possible. 489 */ 490 static void pstgrowblock(shinstance *psh, pstack_block *pst, size_t nbytes, size_t tocopy) 491 { 492 struct stack_block *top = pst->top; 493 size_t blocksize; 494 495 assert(pst->avail < nbytes); /* only called when we need more space */ 496 assert(tocopy <= pst->avail); 497 498 /* Double the size used thus far and add some fudge and alignment. Make 499 sure to at least allocate MINSIZE. */ 500 blocksize = K_MAX(K_ALIGN_Z(pst->avail * 2 + 100 + offsetof(struct stack_block, space), 64), MINSIZE); 501 502 /* If that isn't sufficient, do request size w/ some fudge and alignment. */ 503 if (blocksize < nbytes + offsetof(struct stack_block, space)) 504 blocksize = K_ALIGN_Z(nbytes + offsetof(struct stack_block, space) + 100, 1024); 505 506 /* 507 * Reallocate the current stack node if we can. 508 */ 509 if ( pst->nextbyte == &top->space[0] /* can't have anything else in the block */ 510 && top->prev != NULL /* first block is embedded in pst and cannot be reallocated */ ) { 511 top = (struct stack_block *)ckrealloc(psh, top, blocksize); 512 pst->top = top; 513 pst->topsize = blocksize - offsetof(struct stack_block, space); 514 pst->avail = blocksize - offsetof(struct stack_block, space); 515 pst->nextbyte = top->space; 516 } 517 /* 518 * Otherwise allocate a new node and copy over the avail bytes 519 * from the old one. 520 */ 521 else { 522 char const * const copysrc = pst->nextbyte; 523 pstallocnewblock(psh, pst, nbytes); 524 assert(pst->avail >= nbytes); 525 assert(pst->avail >= tocopy); 526 memcpy(pst->nextbyte, copysrc, tocopy); 527 } 528 } 529 530 K_INLINE void *pstallocint(shinstance *psh, pstack_block *pst, size_t nbytes) 531 { 532 void *ret; 533 534 /* 535 * Align the size and make sure we've got sufficient bytes available: 536 */ 537 nbytes = SHELL_ALIGN(nbytes); 538 if (pst->avail >= nbytes && (ssize_t)pst->avail >= 0) { /* likely*/ } 539 else pstallocnewblock(psh, pst, nbytes); 540 541 /* 542 * Carve out the return block. 543 */ 544 ret = pst->nextbyte; 545 pst->nextbyte += nbytes; 546 pst->avail -= nbytes; 547 pst->bytesalloced += nbytes; 548 pst->allocations += 1; 549 return ret; 550 } 551 552 #endif KASH_SEPARATE_PARSER_ALLOCATOR 553 554 356 555 void *pstalloc(struct shinstance *psh, size_t nbytes) 357 556 { 557 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 558 return pstallocint(psh, psh->curpstack, nbytes); 559 #else 358 560 return stalloc(psh, nbytes); 561 #endif 359 562 } 360 563 361 564 union node *pstallocnode(struct shinstance *psh, size_t nbytes) 362 565 { 566 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 567 pstack_block *pst = psh->curpstack; 568 pst->nodesalloced++; 569 return (union node *)pstallocint(psh, pst, nbytes); 570 #else 363 571 return (union node *)pstalloc(psh, nbytes); 572 #endif 364 573 } 365 574 366 575 struct nodelist *pstalloclist(struct shinstance *psh) 367 576 { 577 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 578 pstack_block *pst = psh->curpstack; 579 pst->entriesalloced++; 580 return (struct nodelist *)pstallocint(psh, pst, sizeof(struct nodelist)); 581 #endif 368 582 return (struct nodelist *)pstalloc(psh, sizeof(struct nodelist)); 369 583 } … … 372 586 { 373 587 if (str) { 374 size_t nbytes = strlen(str) + 1; 588 size_t const nbytes = strlen(str) + 1; 589 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 590 pstack_block *pst = psh->curpstack; 591 pst->strbytesalloced += SHELL_ALIGN(nbytes); 592 return (char *)memcpy(pstallocint(psh, pst, nbytes), str, nbytes); 593 #else 375 594 return (char *)memcpy(pstalloc(psh, nbytes), str, nbytes); 595 #endif 376 596 } 377 597 return NULL; … … 380 600 char *pstmakestrspace(struct shinstance *psh, size_t minbytes, char *end) 381 601 { 602 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 603 pstack_block *pst = psh->curpstack; 604 size_t const len = end - pst->nextbyte; 605 606 assert(pst->avail - pst->strleft == len); 607 TRACE2((psh, "pstmakestrspace: len=%u minbytes=%u (=> %u)\n", len, minbytes, len + minbytes)); 608 609 pstgrowblock(psh, pst, minbytes + len, len); 610 611 pst->strleft = pst->avail - len; 612 return pst->nextbyte + len; 613 614 #else 382 615 size_t const len = end - stackblock(psh); 616 383 617 assert(stackblocksize(psh) - psh->sstrnleft == len); 384 TRACE2((psh, "pstmakestrspace: len=%u minbytes=%u (=> %u)\n", len, minbytes, len + minbytes)); 618 TRACE2((psh, "pstmakestrspace: len=%u minbytes=%u (=> %u)\n", len, minbytes, len + minbytes)); 619 385 620 minbytes += len; 386 621 while (stackblocksize(psh) < minbytes) 387 622 growstackblock(psh); 623 388 624 psh->sstrnleft = (int)(stackblocksize(psh) - len); 389 625 return (char *)stackblock(psh) + len; 626 #endif 390 627 } 391 628 … … 393 630 char *pstputcgrow(shinstance *psh, char *end, char c) 394 631 { 395 psh->sstrnleft++; /* PSTPUTC() already incremented it. */ 632 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 633 pstack_block *pst = psh->curpstack; 634 pst->strleft++; /* PSTPUTC() already incremented it. */ 635 end = pstmakestrspace(psh, 1, end); 636 assert(pst->strleft > 0); 637 pst->strleft--; 638 #else 639 psh->sstrnleft++; /* PSTPUTC() already incremented it. */ 396 640 end = pstmakestrspace(psh, 1, end); 397 641 assert(psh->sstrnleft > 0); 398 642 psh->sstrnleft--; 643 #endif 399 644 *end++ = c; 400 645 return end; … … 404 649 char *pstgrabstr(struct shinstance *psh, char *end) 405 650 { 651 #ifdef KASH_SEPARATE_PARSER_ALLOCATOR 652 pstack_block *pst = psh->curpstack; 653 char * const pstart = pst->nextbyte; 654 size_t nbytes = (size_t)(end - pstart); 655 656 assert((uintptr_t)end > (uintptr_t)pstart); 657 assert(end[-1] == '\0'); 658 assert(SHELL_ALIGN((uintptr_t)pstart) == (uintptr_t)pstart); 659 assert(pst->avail - pst->strleft >= nbytes); 660 661 nbytes = SHELL_ALIGN(nbytes); /** @todo don't align strings, align the other allocations. */ 662 pst->nextbyte += nbytes; 663 pst->avail -= nbytes; 664 pst->strbytesalloced += nbytes; 665 666 return pstart; 667 668 #else 406 669 char * const pstart = stackblock(psh); 407 670 size_t nbytes = (size_t)(end - pstart); … … 417 680 418 681 return pstart; 419 } 420 682 #endif 683 } 684
Note:
See TracChangeset
for help on using the changeset viewer.