Ejemplo n.º 1
0
/*
 * Release a Storage Pool
 * 
 * Frees all dynamic storage acquired for a storage pool.
 * This function is normally called just prior to a module's unloading.
 *
 * Arguments:
 *	sip	pointer to sp_info for storage pool
 *
 * Returns:
 *	none
 *
 */
void
atm_release_pool(struct sp_info *sip)
{
	struct sp_chunk	*scp, *scp_next;

	crit_enter();
	/*
	 * Free each chunk in pool
	 */
	for (scp = sip->si_poolh; scp; scp = scp_next) {

		/*
		 * Check for memory leaks
		 */
		if (scp->sc_used)
			panic("atm_release_pool: unfreed blocks");

		scp_next = scp->sc_next;

		KM_FREE((caddr_t)scp, sip->si_chunksiz, M_DEVBUF);
	}

	/*
	 * Update pool controls
	 */
	sip->si_poolh = NULL;
	sip->si_chunks = 0;
	sip->si_total = 0;
	sip->si_free = 0;

	/*
	 * Unlink pool from active chain
	 */
	sip->si_chunksiz = 0;
	UNLINK(sip, struct sp_info, atm_pool_head, si_next);
	crit_exit();
	return;
}
Ejemplo n.º 2
0
/*
 * Procedure to release a buffer previously allocated from adapter
 * RAM. When possible, we'll compact memory.
 *
 * Arguments:
 *	eup		pointer to per unit structure
 *	base		base adapter address of buffer to be freed
 *
 * Returns:
 *	none
 *
 */
void
eni_free_buffer(Eni_unit *eup, caddr_t base)
{
    Mbd	*eptr = eup->eu_memmap;
    int	nclicks;

    /* Look through entire list */
    while ( eptr )
    {
        /* Is this the buffer to be freed? */
        if ( eptr->base == base )
        {
            /*
             * We're probably asking for trouble but,
             * assume this is it.
             */
            if ( eptr->state != MEM_INUSE )
            {
                eup->eu_stats.eni_st_drv.drv_mm_notuse++;
                /* Huh? Something's wrong */
                return;
            }
            /* Reset state to FREE */
            eptr->state = MEM_FREE;

            /* Determine size for stats info */
            for ( nclicks = 0; nclicks < ENI_BUF_NBIT; nclicks++ )
                if ( ( 1 << nclicks ) * ENI_BUF_PGSZ == eptr->size )
                    break;

            /* Valid size? Yes - decrement inuse count */
            if ( nclicks < ENI_BUF_NBIT )
                eup->eu_memclicks[nclicks]--;

            /* Try to compact neighbors */
            /* with previous */
            if ( eptr->prev )
                if ( eptr->prev->state == MEM_FREE )
                {
                    Mbd	*etmp = eptr;
                    /* Add to previous block */
                    eptr->prev->size += eptr->size;
                    /* Set prev block to skip this one */
                    eptr->prev->next = eptr->next;
                    /* Set next block to skip this one */
                    if ( eptr->next )
                        eptr->next->prev = eptr->prev;
                    /* Reset to where we want to be */
                    eptr = eptr->prev;
                    /* and free this element */
                    (void)KM_FREE(etmp, etmp->size, M_DEVBUF);
                }
            /* with next */
            if ( eptr->next )
                if ( eptr->next->state == MEM_FREE )
                {
                    Mbd	*etmp = eptr->next;

                    /* add following block in */
                    eptr->size += etmp->size;
                    /* set next next block to skip next block */
                    if ( etmp->next )
                        etmp->next->prev = eptr;
                    /* skip next block */
                    eptr->next = etmp->next;
                    /* and free next element */
                    (void)KM_FREE(etmp, etmp->size, M_DEVBUF);
                }
            /*
             * We've freed the buffer and done any compaction,
             * we needn't look any further...
             */
            return;
        }
        eptr = eptr->next;
    }

    if ( eptr == NULL )
    {
        /* Oops - failed to find the buffer. This is BAD */
        eup->eu_stats.eni_st_drv.drv_mm_notfnd++;
    }

}
Ejemplo n.º 3
0
/*
 * Storage Pool Compaction
 * 
 * Called periodically in order to perform compaction of the
 * storage pools.  Each pool will be checked to see if any chunks 
 * can be freed, taking some care to avoid freeing too many chunks
 * in order to avoid memory thrashing.
 *
 * Called from a critical section.
 *
 * Arguments:
 *	tip	pointer to timer control block (atm_compactimer)
 *
 * Returns:
 *	none
 *
 */
static void
atm_compact(struct atm_time *tip)
{
	struct sp_info	*sip;
	struct sp_chunk	*scp;
	int		i;
	struct sp_chunk	*scp_prev;

	/*
	 * Check out all storage pools
	 */
	for (sip = atm_pool_head; sip; sip = sip->si_next) {

		/*
		 * Always keep a minimum number of chunks around
		 */
		if (sip->si_chunks <= SPOOL_MIN_CHUNK)
			continue;

		/*
		 * Maximum chunks to free at one time will leave
		 * pool with at least 50% utilization, but never
		 * go below minimum chunk count.
		 */
		i = ((sip->si_free * 2) - sip->si_total) / sip->si_blkcnt;
		i = MIN(i, sip->si_chunks - SPOOL_MIN_CHUNK);

		/*
		 * Look for chunks to free
		 */
		scp_prev = NULL;
		for (scp = sip->si_poolh; scp && i > 0; ) {

			if (scp->sc_used == 0) {

				/*
				 * Found a chunk to free, so do it
				 */
				if (scp_prev) {
					scp_prev->sc_next = scp->sc_next;
					if (sip->si_poolt == scp)
						sip->si_poolt = scp_prev;
				} else
					sip->si_poolh = scp->sc_next;

				KM_FREE((caddr_t)scp, sip->si_chunksiz,
					M_DEVBUF);

				/*
				 * Update pool controls
				 */
				sip->si_chunks--;
				sip->si_total -= sip->si_blkcnt;
				sip->si_free -= sip->si_blkcnt;
				i--;
				if (scp_prev)
					scp = scp_prev->sc_next;
				else
					scp = sip->si_poolh;
			} else {
				scp_prev = scp;
				scp = scp->sc_next;
			}
		}
	}

	/*
	 * Restart the compaction timer
	 */
	atm_timeout(&atm_compactimer, SPOOL_COMPACT, atm_compact);

	return;
}