|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/map.h" ! 3: #include "sys/dmap.h" ! 4: ! 5: /* ! 6: * resource maps, for dishing out pieces of things ! 7: * that can be described by integers ! 8: * ! 9: * to use them: ! 10: * declare struct map xxmap[N] ! 11: * where N is the largest number of pieces free parts of the resource may be ! 12: * fragmented into ! 13: * rminit to set up the map ! 14: * rmalloc to allocate pieces ! 15: * rmfree to give them back ! 16: * ! 17: * the map is an array of (size, address) pairs, ! 18: * ordered by address. ! 19: * allocation is first-fit. ! 20: * if the map becomes very fragmented, ! 21: * and therefore too big to fit, ! 22: * some of the resource may be lost. ! 23: * the first piece of the map is magic, and holds an end-marker; ! 24: * the last piece is kept empty ! 25: */ ! 26: ! 27: /* ! 28: * initialize struct map mp[mapsize] ! 29: * to hold size pieces starting at addr ! 30: */ ! 31: rminit(mp, mapsize, size, addr) ! 32: register struct map *mp; ! 33: int mapsize; ! 34: int size, addr; ! 35: { ! 36: ! 37: if (mapsize < 3) ! 38: panic("rminit"); ! 39: mp->m_end = mapsize - 1; /* leave an end-marker */ ! 40: mp++; ! 41: mp->m_size = size; ! 42: mp->m_addr = addr; ! 43: mp++; ! 44: mp->m_size = 0; ! 45: mp->m_addr = 0; ! 46: } ! 47: ! 48: rmalloc(mp, size) ! 49: register struct map *mp; ! 50: { ! 51: register int addr; ! 52: register struct map *bp; ! 53: ! 54: if (size <= 0) ! 55: panic("rmalloc"); ! 56: for (bp = mp+1; bp->m_size; bp++) { ! 57: if (bp->m_size >= size) { ! 58: addr = bp->m_addr; ! 59: bp->m_addr += size; ! 60: if ((bp->m_size -= size) == 0) { ! 61: do { ! 62: bp++; ! 63: (bp-1)->m_addr = bp->m_addr; ! 64: } while ((bp-1)->m_size = bp->m_size); ! 65: } ! 66: return (addr); ! 67: } ! 68: } ! 69: return (0); ! 70: } ! 71: ! 72: /* ! 73: * special version of rmalloc, to handle swapmap silliness ! 74: * historical; get rid of it later ! 75: */ ! 76: srmalloc(mp, size) ! 77: register struct map *mp; ! 78: { ! 79: register int addr; ! 80: register struct map *bp; ! 81: swblk_t first, rest; ! 82: ! 83: if (size <= 0 || size > dmmax) ! 84: panic("rmalloc"); ! 85: for (bp = mp+1; bp->m_size; bp++) { ! 86: if (bp->m_size >= size) { ! 87: /* ! 88: * If allocating from swapmap, ! 89: * then have to respect interleaving ! 90: * boundaries. ! 91: */ ! 92: first = dmmax - bp->m_addr%dmmax; ! 93: if (first<bp->m_size && first<size) { ! 94: if (bp->m_size - first < size) ! 95: continue; ! 96: addr = bp->m_addr + first; ! 97: rest = bp->m_size - first - size; ! 98: bp->m_size = first; ! 99: if (rest) ! 100: rmfree(mp, rest, addr+size); ! 101: return (addr); ! 102: } ! 103: addr = bp->m_addr; ! 104: bp->m_addr += size; ! 105: if ((bp->m_size -= size) == 0) { ! 106: do { ! 107: bp++; ! 108: (bp-1)->m_addr = bp->m_addr; ! 109: } while ((bp-1)->m_size = bp->m_size); ! 110: } ! 111: if (addr % CLSIZE) ! 112: panic("rmalloc swapmap"); ! 113: return (addr); ! 114: } ! 115: } ! 116: return (0); ! 117: } ! 118: ! 119: /* ! 120: * free a chunk ! 121: * hack: if we need to create a new map entry ! 122: * and there aren't any left, ! 123: * discard the next-to-last, ! 124: * as the last one tends to be larger ! 125: */ ! 126: rmfree(mp, size, addr) ! 127: register struct map *mp; ! 128: register int size, addr; ! 129: { ! 130: register struct map *bp, *xp; ! 131: ! 132: if (addr <= 0 || size <= 0) ! 133: panic("rmfree"); ! 134: for (bp = mp + 1; bp->m_addr <= addr && bp->m_size != 0; bp++) ! 135: continue; ! 136: /* ! 137: * can merge into previous block, or both sides? ! 138: */ ! 139: xp = bp - 1; ! 140: if (bp > mp + 1 && xp->m_addr + xp->m_size >= addr) { ! 141: if (xp->m_addr + xp->m_size > addr) ! 142: panic("dup rmfree"); ! 143: xp->m_size += size; ! 144: if (bp->m_addr && addr+size >= bp->m_addr) { ! 145: if (addr+size > bp->m_addr) ! 146: panic("dup rmfree"); ! 147: xp->m_size += bp->m_size; ! 148: while (bp->m_size) { ! 149: bp[0] = bp[1]; ! 150: bp++; ! 151: } ! 152: } ! 153: return; ! 154: } ! 155: /* ! 156: * can merge into next block? ! 157: */ ! 158: if (addr+size >= bp->m_addr && bp->m_size) { ! 159: if (addr+size > bp->m_addr) ! 160: panic("dup rmfree"); ! 161: bp->m_addr -= size; ! 162: bp->m_size += size; ! 163: return; ! 164: } ! 165: /* ! 166: * can't merge; make a new entry before bp ! 167: */ ! 168: xp = bp; ! 169: while (bp->m_size) ! 170: bp++; ! 171: if (bp-mp >= mp->m_end) { /* overflow? */ ! 172: printf("rmfree: map %x overflow, lost %d-%d\n", mp, ! 173: bp[-2].m_addr, bp[-2].m_size+bp[-2].m_addr); ! 174: bp[-2] = bp[-1]; ! 175: bp[-1] = bp[0]; ! 176: bp--; ! 177: } ! 178: do { ! 179: bp[1] = bp[0]; ! 180: bp--; ! 181: } while (bp >= xp); ! 182: xp->m_size = size; ! 183: xp->m_addr = addr; ! 184: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.