Repository: ossrs/srs
File: trunk/3rdparty/st-srs/stk.c (C)

Code before:

static char *_st_new_stk_segment(int size);
static void _st_delete_stk_segment(char *vaddr, int size);

_st_stack_t *_st_stack_new(int stack_size)
{
    _st_clist_t *qp;
    _st_stack_t *ts;
    int extra;

#ifdef MD_CACHE_STACK
    for (qp = _st_free_stacks.next; qp != &_st_free_stacks; qp = qp->next) {
        ts = _ST_THREAD_STACK_PTR(qp);
        if (ts->stk_size >= stack_size) {
            /* Found a stack that is big enough */
            ST_REMOVE_LINK(&ts->links);
            _st_num_free_stacks--;
            ts->links.next = NULL;
            ts->links.prev = NULL;
            returnt ts;
        }
    }
#endif

    extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0;
#ifndef MD_CACHE_STACK
    for (qp = _st_free_stacks.next; qp != &_st_free_stacks;) {
        ts = _ST_THREAD_STACK_PTR(qp);
        // Before qp is freed, move to next one, because the qp will be freed when free the ts.
        qp = qp->next;

        ST_REMOVE_LINK(&ts->links);
        _st_num_free_stacks--;

#if defined(DEBUG) && !defined(MD_NO_PROTECT)
        mprotect(ts->vaddr, REDZONE, PROT_READ | PROT_WRITE);
        mprotect(ts->stk_top + extra, REDZONE, PROT_READ | PROT_WRITE);
#endif

        _st_delete_stk_segment(ts->vaddr, ts->vaddr_size);
        free(ts);
    }
#endif
    
    /* Make a new thread stack object. */
    if ((ts = (_st_stack_t *)calloc(1, sizeof(_st_stack_t))) == NULL)
        return NULL;
    ts->vaddr_size = stack_size + 2*REDZONE + extra;
    ts->vaddr = _st_new_stk_segment(ts->vaddr_size);
    if (!ts->vaddr) {
        free(ts);

Review comment (performance):
if don't cache stack, why not free `_st_stack_t` in `_st_stack_free`, don't use `_st_free_stacks` to store the freed stack?
The stack still not freed in `_st_free_stacks`, else a new coroutine started and request a new stack here.

Code after:

static char *_st_new_stk_segment(int size);
static void _st_delete_stk_segment(char *vaddr, int size);

_st_stack_t *_st_stack_new(int stack_size)
{
    _st_clist_t *qp;
    _st_stack_t *ts;
    int extra;

#ifdef MD_CACHE_STACK
    for (qp = _st_free_stacks.next; qp != &_st_free_stacks; qp = qp->next) {
        ts = _ST_THREAD_STACK_PTR(qp);
        if (ts->stk_size >= stack_size) {
            /* Found a stack that is big enough */
            ST_REMOVE_LINK(&ts->links);
            _st_num_free_stacks--;
            ts->links.next = NULL;
            ts->links.prev = NULL;
            return ts;
        }
    }
#endif

    extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0;
#ifndef MD_CACHE_STACK
    for (qp = _st_free_stacks.next; qp != &_st_free_stacks;) {
        ts = _ST_THREAD_STACK_PTR(qp);
        // Before qp is freed, move to next one, because the qp will be freed when free the ts.
        qp = qp->next;

        ST_REMOVE_LINK(&ts->links);
        _st_num_free_stacks--;

#if defined(DEBUG) && !defined(MD_NO_PROTECT)
        mprotect(ts->vaddr, REDZONE, PROT_READ | PROT_WRITE);
        mprotect(ts->stk_top + extra, REDZONE, PROT_READ | PROT_WRITE);
#endif

        _st_delete_stk_segment(ts->vaddr, ts->vaddr_size);
        free(ts);
    }
#endif
    
    /* Make a new thread stack object. */
    if ((ts = (_st_stack_t *)calloc(1, sizeof(_st_stack_t))) == NULL)
        return NULL;
    ts->vaddr_size = stack_size + 2*REDZONE + extra;
    ts->vaddr = _st_new_stk_segment(ts->vaddr_size);
    if (!ts->vaddr) {
        free(ts);