1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: 18: 19: 20:
21:
22: #include "sysmgr.h"
23: #include "cache_info.h"
24: #include <sys/rominfo.h>
25: #include <sys/imalloc.h>
26:
27: 28: 29:
30: typedef struct {
31: VB mem[2*1024];
32: } PAGE;
33: #define PAGESZ ( sizeof(PAGE) )
34:
35: typedef UINT PN;
36:
37: 38: 39:
40: EXPORT UW smPageCount( UW byte )
41: {
42: return (byte + (PAGESZ-1)) / PAGESZ;
43: }
44:
45: 46: 47:
48: typedef struct {
49: BOOL cont:1;
50: BOOL use:1;
51: PN next:30;
52: UINT atr:2;
53: PN prev:30;
54: } PAGEQUE;
55:
56: #define USE TRUE
57: #define FREE FALSE
58: #define CONT TRUE
59: #define ONE FALSE
60:
61: CONST LOCAL PAGEQUE _clrPageQue = { ONE, FREE, 0, 0, 0 };
62:
63: #define clrPageQue(q) ( (q) = _clrPageQue )
64:
65:
66: #define NumOfPages(q) ( ( (q)->cont )? ((q)+1)->next: 1 )
67:
68: 69: 70:
71: #define MB_NOCACHE 1
72:
73: 74: 75: 76: 77: 78:
79: typedef struct {
80: INT maxpage;
81: INT freepage;
82: PAGEQUE *pageque; 83:
84: PAGE *top_page;
85: } PAGETBL;
86:
87: #define freeque pageque[0]
88:
89: #define _PageAdr(pn, pt) ( (void*)((pt)->top_page + ((pn) - 1)) )
90: #define _PageNo(adr, pt) ( (PN)(((PAGE*)(adr) - (pt)->top_page) + 1) )
91:
92:
93:
94: 95: 96:
97: LOCAL PAGETBL SysMemTbl;
98: #if USE_NOCACHE_MEMTBL
99: LOCAL PAGETBL NoCacheMemTbl;
100: #endif
101:
102: 103: 104: 105: 106:
107: LOCAL FastLock MemLock = { -1, -1 };
108: #define LockMEM() Lock(&MemLock)
109: #define UnlockMEM() Unlock(&MemLock)
110:
111:
112: #define OBJNAME_MMLOCK "Mem"
113:
114:
115:
116: Inline void* PageAdr( PN pn, PAGETBL *pt )
117: {
118: void* adr = _PageAdr(pn, pt);
119:
120: if ( (pt->pageque[pn].atr & MB_NOCACHE) != 0 ) {
121: adr = NoCachingAddr(adr);
122: }
123: return adr;
124: }
125: Inline PN PageNo( CONST void *adr, PAGETBL *pt )
126: {
127: adr = CachingAddr(adr);
128: return _PageNo(adr, pt);
129: }
130:
131: 132: 133: 134:
135: LOCAL BOOL chkadr( CONST void *adr, PAGETBL *pt )
136: {
137: adr = CachingAddr(adr);
138: if ( adr >= (void*)pt->top_page && adr < (void*)(pt->top_page + pt->maxpage) ) {
139: if ( ((UINT)adr % PAGESZ) == 0 ) {
140: return TRUE;
141: }
142: }
143: return FALSE;
144: }
145:
146: 147: 148:
149: Inline PAGEQUE setPageQue( BOOL u, BOOL c, PN n, PN p, UINT a )
150: {
151: PAGEQUE q;
152: q.use = u;
153: q.cont = c;
154: q.next = n;
155: q.prev = p;
156: q.atr = a;
157: return q;
158: }
159:
160: 161: 162:
163: Inline void initPageQue( PN pn, PAGETBL *pt )
164: {
165: pt->pageque[pn].next = pt->pageque[pn].prev = pn;
166: }
167:
168: 169: 170: 171:
172: Inline void insertPageQue( PN que, PN ent, PAGETBL *pt )
173: {
174: PAGEQUE *qp = &pt->pageque[que];
175: PAGEQUE *ep = &pt->pageque[ent];
176:
177: ep->prev = qp->prev;
178: ep->next = que;
179: pt->pageque[qp->prev].next = ent;
180: qp->prev = ent;
181: }
182:
183: 184: 185: 186:
187: LOCAL void removePageQue( PN ent, PAGETBL *pt )
188: {
189: PAGEQUE *ep = &pt->pageque[ent];
190:
191: if ( ep->next != ent ) {
192: pt->pageque[ep->prev].next = ep->next;
193: pt->pageque[ep->next].prev = ep->prev;
194: }
195: }
196:
197: 198: 199:
200: Inline BOOL isEmptyPageQue( PN que, PAGETBL *pt )
201: {
202: return ( pt->pageque[que].next == que );
203: }
204:
205: 206: 207: 208: 209: 210:
211: LOCAL PN searchFreeQue( INT n, PAGETBL *pt )
212: {
213: PAGEQUE *pageque = pt->pageque;
214: PN pn = 0;
215:
216: while ( (pn = pageque[pn].next) > 0 ) {
217: if ( NumOfPages(&pageque[pn]) >= n ) {
218: return pn;
219: }
220: }
221: return 0;
222: }
223:
224: 225: 226: 227: 228:
229: LOCAL void appendFreePages( PN pn, INT n, PAGETBL *pt )
230: {
231: PN ins;
232: PAGEQUE *pq = &pt->pageque[pn];
233:
234:
235: pq->use = FREE;
236: pq->cont = ( n > 1 )? CONT: ONE;
237: pq->atr = 0;
238: if ( n > 1 ) {
239: pq[1] = setPageQue(FREE, CONT, n, 0, 0);
240: }
241: if ( n > 2 ) {
242: pq[n-1] = setPageQue(FREE, CONT, n, 0, 0);
243: }
244:
245:
246: ins = searchFreeQue(n, pt);
247:
248:
249: insertPageQue(ins, pn, pt);
250: }
251:
252: 253: 254:
255: Inline void setUsePages( PN pn, INT n, UINT atr, PAGETBL *pt )
256: {
257: PAGEQUE *pq = &pt->pageque[pn];
258:
259:
260: pq->use = USE;
261: pq->cont = ( n > 1 )? CONT: ONE;
262: pq->atr = atr;
263: if ( n > 1 ) {
264: pq[1] = setPageQue(USE, CONT, n, 0, 0);
265: }
266: if ( n > 2 ) {
267: pq[n-1] = setPageQue(USE, CONT, n, 0, 0);
268: }
269:
270: initPageQue(pn, pt);
271: }
272:
273: 274: 275:
276: LOCAL void* getPage( INT nblk, UINT atr, PAGETBL *pt )
277: {
278: PN pn;
279: INT free;
280:
281:
282: pn = searchFreeQue(nblk, pt);
283: if ( pn == 0 ) {
284: return NULL;
285: }
286: free = NumOfPages(&pt->pageque[pn]);
287:
288: 289:
290: removePageQue(pn, pt);
291:
292:
293: setUsePages(pn, nblk, atr, pt);
294: free -= nblk;
295:
296: if ( free > 0 ) {
297:
298: appendFreePages(pn + (UINT)nblk, free, pt);
299: }
300:
301: pt->freepage -= nblk;
302:
303: return PageAdr(pn, pt);
304: }
305:
306: 307: 308: 309:
310: LOCAL INT relPage( CONST void *adr, PAGETBL *pt )
311: {
312: PN pn;
313: PAGEQUE *pq;
314: INT nblk, free;
315:
316: pn = PageNo(adr, pt);
317: pq = &pt->pageque[pn];
318:
319: if ( pq->use == FREE ) {
320: return E_PAR;
321: }
322:
323:
324: free = nblk = NumOfPages(pq);
325:
326:
327: if ( pn + (UINT)nblk <= pt->maxpage && (pq+(UINT)nblk)->use == FREE ) {
328:
329:
330: removePageQue(pn+(PN)nblk, pt);
331:
332:
333: nblk += NumOfPages(pq+nblk);
334: }
335:
336:
337: if ( pn > 1 && (pq-1)->use == FREE ) {
338:
339:
340: INT n = ( (pq-1)->cont )? (pq-1)->next: 1;
341:
342:
343: removePageQue(pn-(PN)n, pt);
344:
345:
346: pn -= (UINT)n;
347: nblk += n;
348:
349: 350: 351:
352: pq->use = FREE;
353: }
354:
355:
356: appendFreePages(pn, nblk, pt);
357:
358: pt->freepage += free;
359:
360: return free;
361: }
362:
363: 364: 365:
366: LOCAL ER initPageTbl( void *top, void *end, PAGETBL *pt )
367: {
368: INT memsz, npage;
369:
370:
371: top = (void*)(((UINT)top + 7) & ~0x00000007U);
372: memsz = (INT)((UINT)end - (UINT)top);
373:
374:
375: pt->pageque = (PAGEQUE*)top;
376:
377:
378: npage = (INT)(((UINT)memsz - sizeof(PAGEQUE)) / (PAGESZ + sizeof(PAGEQUE)));
379:
380: 381:
382: pt->top_page = (PAGE*)(((UINT)(pt->pageque + npage + 1)
383: + (PAGESZ-1)) / PAGESZ * PAGESZ);
384:
385:
386: npage = (INT)(((UINT)end - (UINT)pt->top_page) / (UINT)PAGESZ);
387: pt->maxpage = npage;
388: pt->freepage = npage;
389:
390:
391: clrPageQue(pt->freeque);
392: appendFreePages(1, npage, pt);
393:
394: return E_OK;
395: }
396:
397:
398:
399: 400: 401: 402:
403: EXPORT void* GetSysMemBlk( INT nblk, UINT attr )
404: {
405: PAGETBL *pt;
406: void *adr;
407: UINT mb_atr;
408:
409:
410: #if USE_NOCACHE_MEMTBL
411: pt = ( (attr & TA_NOCACHE) != 0 )? &NoCacheMemTbl: &SysMemTbl;
412: #else
413: pt = &SysMemTbl;
414: #endif
415:
416:
417: mb_atr = 0;
418: if ( (attr & TA_NOCACHE) != 0 ) {
419: mb_atr |= MB_NOCACHE;
420: }
421:
422:
423: LockMEM();
424: adr = getPage(nblk, mb_atr, pt);
425: UnlockMEM();
426:
427: #ifdef DEBUG
428: if ( adr == NULL ) {
429: TM_DEBUG_PRINT(("GetSysMemBlk E_NOMEM\n"));
430: }
431: #endif
432: return adr;
433: }
434:
435: 436: 437:
438: EXPORT ER RelSysMemBlk( CONST void *addr )
439: {
440: PAGETBL *pt;
441: INT free;
442: ER ercd;
443:
444: pt = ( chkadr(addr, &SysMemTbl) )? &SysMemTbl:
445: #if USE_NOCACHE_MEMTBL
446: ( chkadr(addr, &NoCacheMemTbl) )? &NoCacheMemTbl:
447: #endif
448: NULL;
449: if ( pt == NULL ) {
450: ercd = E_PAR;
451: goto err_ret;
452: }
453:
454: LockMEM();
455: free = relPage(addr, pt);
456: UnlockMEM();
457: if ( free < E_OK ) {
458: ercd = free;
459: goto err_ret;
460: }
461:
462:
463: FlushCache(addr, free * (W)PAGESZ);
464:
465: return E_OK;
466:
467: err_ret:
468: TM_DEBUG_PRINT(("RelSysMemBlk ercd = %d\n", ercd));
469: return ercd;
470: }
471:
472: 473: 474:
475: EXPORT ER RefSysMemInfo( T_RSMB *pk_rsmb )
476: {
477: LockMEM();
478: pk_rsmb->blksz = PAGESZ;
479: pk_rsmb->total = SysMemTbl.maxpage;
480: pk_rsmb->free = SysMemTbl.freepage;
481: UnlockMEM();
482:
483: return E_OK;
484: }
485:
486:
487:
488: 489: 490: 491:
492: EXPORT ER init_memmgr( void )
493: {
494:
495: IMPORT void *lowmem_top, *lowmem_limit;
496: void *memend;
497: ER ercd;
498:
499:
500: ercd = _tk_get_cfn(SCTAG_REALMEMEND, (INT*)&memend, 1);
501: if ( ercd < 1 || (UINT)memend > (UINT)lowmem_limit ) {
502: memend = lowmem_limit;
503: }
504:
505:
506: ercd = initPageTbl(lowmem_top, memend, &SysMemTbl);
507: if ( ercd < E_OK ) {
508: goto err_ret;
509: }
510:
511: lowmem_top = memend;
512:
513: #if USE_NOCACHE_MEMTBL
514:
515: ercd = initPageTbl(NoCacheMemoryTop, NoCacheMemoryEnd, &NoCacheMemTbl);
516: if ( ercd < E_OK ) {
517: goto err_ret;
518: }
519: #endif
520:
521: return E_OK;
522:
523: err_ret:
524: TM_DEBUG_PRINT(("init_memmgr ercd = %d\n", ercd));
525: return ercd;
526: }
527:
528: 529: 530: 531:
532: EXPORT ER start_memmgr( void )
533: {
534: ER ercd;
535:
536:
537: ercd = CreateLock(&MemLock, OBJNAME_MMLOCK);
538: if ( ercd < E_OK ) {
539: goto err_ret;
540: }
541:
542: return E_OK;
543:
544: err_ret:
545: TM_DEBUG_PRINT(("start_memmgr ercd = %d\n", ercd));
546: return ercd;
547: }
548:
549: 550: 551:
552: EXPORT ER finish_memmgr( void )
553: {
554: return E_OK;
555: }