MEMMGR.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:16k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /*                                                              */
  3. /*                          memmgr.c                            */
  4. /*                                                              */
  5. /*               Memory Manager for Core Allocation             */
  6. /*                                                              */
  7. /*                      Copyright (c) 1995                      */
  8. /*                      Pasquale J. Villani                     */
  9. /*                      All Rights Reserved                     */
  10. /*                                                              */
  11. /* This file is part of DOS-C.                                  */
  12. /*                                                              */
  13. /* DOS-C is free software; you can redistribute it and/or       */
  14. /* modify it under the terms of the GNU General Public License  */
  15. /* as published by the Free Software Foundation; either version */
  16. /* 2, or (at your option) any later version.                    */
  17. /*                                                              */
  18. /* DOS-C is distributed in the hope that it will be useful, but */
  19. /* WITHOUT ANY WARRANTY; without even the implied warranty of   */
  20. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
  21. /* the GNU General Public License for more details.             */
  22. /*                                                              */
  23. /* You should have received a copy of the GNU General Public    */
  24. /* License along with DOS-C; see the file COPYING.  If not,     */
  25. /* write to the Free Software Foundation, 675 Mass Ave,         */
  26. /* Cambridge, MA 02139, USA.                                    */
  27. /****************************************************************/
  28. #include "../../hdr/portab.h"
  29. #include "globals.h"
  30. /* $Logfile*/
  31. #ifdef VERSION_STRING
  32. static BYTE *memmgrRcsId = "$Header:   C:/dos-c/src/kernel/memmgr.c_v   1.6   04 Jan 1998 23:15:18   patv  $";
  33. #endif
  34. /* $Log:   C:/dos-c/src/kernel/memmgr.c_v  $
  35.  * 
  36.  *    Rev 1.6   04 Jan 1998 23:15:18   patv
  37.  * Changed Log for strip utility
  38.  * 
  39.  *    Rev 1.5   16 Jan 1997 12:47:00   patv
  40.  * pre-Release 0.92 feature additions
  41.  * 
  42.  *    Rev 1.4   29 May 1996 21:03:34   patv
  43.  * bug fixes for v0.91a
  44.  * 
  45.  *    Rev 1.3   19 Feb 1996  3:21:36   patv
  46.  * Added NLS, int2f and config.sys processing
  47.  * 
  48.  *    Rev 1.2   01 Sep 1995 17:54:20   patv
  49.  * First GPL release.
  50.  * 
  51.  *    Rev 1.1   30 Jul 1995 20:51:58   patv
  52.  * Eliminated version strings in ipl
  53.  * 
  54.  *    Rev 1.0   02 Jul 1995  8:33:08   patv
  55.  * Initial revision.
  56.  */
  57. /* $EndLog$ */
  58. VOID mcb_init();        
  59. VOID mcb_print();
  60. VOID show_chain();
  61. /* The following code is 8086 dependant                         */
  62. #ifdef KERNEL
  63. VOID 
  64. mcb_init (mcb FAR *mcbp, UWORD size)
  65. {
  66. COUNT i;
  67. mcbp -> m_type = MCB_LAST;
  68. mcbp -> m_psp = FREE_PSP;
  69. mcbp -> m_size = size;
  70. for(i = 0; i < 8; i++)
  71. mcbp -> m_name[i] = '';
  72. mem_access_mode = FIRST_FIT;
  73. }
  74. #endif
  75. seg 
  76. far2para (VOID FAR *p)
  77. {
  78. seg u1 = FP_SEG(p);
  79. offset u2 = FP_OFF(p);
  80. ULONG phy_addr;
  81. phy_addr = (((long)u1) << 4) + u2;
  82. return (phy_addr>>4);
  83. }
  84. seg 
  85. long2para (LONG size)
  86. {
  87. return ((size + 0x0f)>>4);
  88. }
  89. VOID FAR *
  90. add_far (VOID FAR *fp, ULONG off)
  91. {
  92. UWORD seg_val;
  93. UWORD off_val;
  94. /* Break far pointer into components                            */
  95. seg_val = FP_SEG(fp);
  96. off_val = FP_OFF(fp);
  97. /* add the offset  to the fp's offset part                      */
  98. off += off_val;
  99. /* make off_val equal to lower part of new value                */
  100. off_val = off & 0xffff;
  101. /* and add top part into seg                                    */
  102. seg_val += ((off & 0x000f0000l) / 0x10);
  103. /* and send back the new pointer                                */
  104. return (VOID FAR *)MK_FP(seg_val, off_val);
  105. }
  106. VOID FAR *
  107. adjust_far (VOID FAR *fp)
  108. {
  109. ULONG linear;
  110. UWORD seg_val;
  111. UWORD off_val;
  112. /* First, convert the segmented pointer to a linear address     */
  113. linear = (((ULONG)FP_SEG(fp)) << 4) + FP_OFF(fp);
  114. /* Break it into segments.                                      */
  115. seg_val = (UWORD)(linear >> 4);
  116. off_val = (UWORD)(linear & 0xf);
  117. /* and return an adddress adjusted to the nearest paragraph     */
  118. /* boundary.                                                    */
  119. return MK_FP(seg_val, off_val);
  120. }
  121. #undef REG
  122. #define REG 
  123. #ifdef KERNEL
  124. COUNT 
  125. DosMemAlloc (UWORD size, COUNT mode, seg FAR *para, UWORD FAR *asize)
  126. {
  127. REG mcb FAR *p;
  128. mcb FAR *q;
  129. COUNT i;
  130. BOOL found;
  131. /* Initialize                                           */
  132. p = (mcb FAR *)(MK_FP(first_mcb, 0));
  133. /* Search through memory blocks                         */
  134. for(q = (mcb FAR *)0, i = 0, found = FALSE; !found; )
  135. {
  136. /* check for corruption                         */
  137. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  138. return DE_MCBDESTRY;
  139. /* Test if free based on mode rules             */
  140. switch(mode)
  141. {
  142. case LAST_FIT:
  143. default:
  144. /* Check for a last fit candidate       */
  145. if(p -> m_size >= size && p -> m_psp == FREE_PSP)
  146. /* keep the last know fit       */
  147. q = p;
  148. /* not free - bump the pointer          */
  149. if(p -> m_type != MCB_LAST)
  150. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  151. /* was there no room (q == 0)?          */
  152. else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
  153. return DE_NOMEM;
  154. /* something was found - continue       */
  155. else
  156. found = TRUE;
  157. break;
  158. case FIRST_FIT:
  159. /* Check for a first fit candidate      */
  160. if(p -> m_size >= size && p -> m_psp == FREE_PSP)
  161. {
  162. q = p;
  163. found = TRUE;
  164. break;
  165. }
  166. /* not free - bump the pointer          */
  167. if(p -> m_type != MCB_LAST)
  168. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  169. /* nothing found till end - no room     */
  170. else
  171. return DE_NOMEM;
  172. break;
  173. case BEST_FIT:
  174. /* Check for a best fit candidate       */
  175. if(p -> m_size >= size && p -> m_psp == FREE_PSP)
  176. {
  177. if(i == 0 || p -> m_size < i)
  178. {
  179. i = p -> m_size;
  180. q = p;
  181. }
  182. }
  183. /* not free - bump the pointer          */
  184. if(p -> m_type != MCB_LAST)
  185. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  186. /* was there no room (q == 0)?          */
  187. else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
  188. return DE_NOMEM;
  189. /* something was found - continue       */
  190. else
  191. found = TRUE;
  192. break;
  193. case LARGEST:
  194. /* Check for a first fit candidate      */
  195. if((p -> m_psp == FREE_PSP) && (i == 0 || p -> m_size > i))
  196. {
  197. size = *asize = i = p -> m_size;
  198. q = p;
  199. }
  200. /* not free - bump the pointer          */
  201. if(p -> m_type != MCB_LAST)
  202. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  203. /* was there no room (q == 0)?          */
  204. else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
  205. return DE_NOMEM;
  206. /* something was found - continue       */
  207. else
  208. found = TRUE;
  209. break;
  210. }
  211. }
  212. p = q;
  213. /* Larger fit case              */
  214. if(p -> m_size > size)
  215. {
  216. if(mode != LAST_FIT)
  217. {
  218. q = MK_FP(far2para((VOID FAR *)p) + size + 1, 0);
  219. /* Always flow m_type up */
  220. /* on alloc             */
  221. q -> m_type = p -> m_type;
  222. p -> m_type = MCB_NORMAL;
  223. p -> m_psp = cu_psp;
  224. q -> m_psp = FREE_PSP;
  225. q -> m_size = p -> m_size - size - 1;
  226. p -> m_size = size;
  227. for(i = 0; i < 8; i++)
  228. p -> m_name[i] = q -> m_name[i] = '';
  229. }
  230. else
  231. {
  232. q = MK_FP(far2para((VOID FAR *)p) + (p -> m_size - size), 0);
  233. /* Always flow m_type up */
  234. /* on alloc             */
  235. q -> m_type = p -> m_type;
  236. p -> m_type = MCB_NORMAL;
  237. q -> m_psp = cu_psp;
  238. p -> m_psp = FREE_PSP;
  239. p -> m_size = p -> m_size - size - 1;
  240. q -> m_size = size;
  241. for(i = 0; i < 8; i++)
  242. p -> m_name[i] = q -> m_name[i] = '';
  243. }
  244. /* Found - return good          */
  245. *para = far2para((VOID FAR *)(mode == LAST_FIT ? (VOID FAR *)q : (VOID FAR *)p));
  246. return SUCCESS;
  247. }
  248. /* Exact fit case               */
  249. else if(p -> m_size == size)
  250. {
  251. p -> m_psp = cu_psp;
  252. for(i = 0; i < 8; i++)
  253. p -> m_name[i] = '';
  254. /* Found - return good          */
  255. *para = far2para((VOID FAR *)(BYTE FAR *)p);
  256. return SUCCESS;
  257. }
  258. else
  259. return DE_MCBDESTRY;
  260. }
  261. seg 
  262. DosMemLargest (seg FAR *size)
  263. {
  264. REG mcb FAR *p;
  265. mcb FAR *q;
  266. COUNT found;
  267. /* Initialize                                           */
  268. p = (mcb FAR *)(MK_FP(first_mcb, 0));
  269. /* Search through memory blocks                         */
  270. for(q = (mcb FAR *)0, *size = 0, found = FALSE; !found; )
  271. {
  272. /* check for corruption                         */
  273. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  274. return DE_MCBDESTRY;
  275. /* Test for largest fit/available               */
  276. if((p -> m_psp == FREE_PSP) && (p -> m_size > *size))
  277. {
  278. *size = p -> m_size;
  279. q = p;
  280. }
  281. /* not free - bump the pointer          */
  282. if(p -> m_type != MCB_LAST)
  283. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  284. /* was there no room (q == 0)?          */
  285. else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
  286. return DE_NOMEM;
  287. /* something was found - continue       */
  288. else
  289. found = TRUE;
  290. }
  291. if( q != 0)
  292. return SUCCESS;
  293. else
  294. return DE_NOMEM;
  295. }
  296. COUNT 
  297. DosMemFree (UWORD para)
  298. {
  299. REG mcb FAR *p, FAR *q;
  300. COUNT i;
  301. /* Initialize                                           */
  302. p = (mcb FAR *)(MK_FP(para, 0));
  303. /* check for corruption                         */
  304. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  305. return DE_INVLDMCB;
  306. /* Mark the mcb as free so that we can later    */
  307. /* merge with other surrounding free mcb's      */
  308. p -> m_psp = FREE_PSP;
  309. for(i = 0; i < 8; i++)
  310. p -> m_name[i] = '';
  311. /* Now merge free blocks                        */
  312. for(p = (mcb FAR *)(MK_FP(first_mcb, 0)); p -> m_type != MCB_LAST; p = q)
  313. {
  314. /* make q a pointer to the next block   */
  315. q = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  316. /* and test for corruption              */
  317. if(q -> m_type != MCB_NORMAL && q -> m_type != MCB_LAST)
  318. return DE_MCBDESTRY;
  319. if(p -> m_psp != FREE_PSP)
  320. continue;
  321. /* test if next is free - if so merge   */
  322. if(q -> m_psp == FREE_PSP)
  323. {
  324. /* Always flow type down on free */
  325. p -> m_type = q -> m_type;
  326. p -> m_size += q -> m_size + 1;
  327. /* and make pointers the same   */
  328. /* since the next free is now   */
  329. /* this block                   */
  330. q = p;
  331. }
  332. }
  333. return SUCCESS;
  334. }
  335. COUNT 
  336. DosMemChange (UWORD para, UWORD size, UWORD *maxSize)
  337. {
  338. REG mcb FAR *p, FAR *q;
  339. REG COUNT i;
  340. /* Initialize                                                   */
  341. p = (mcb FAR *)(MK_FP(--para, 0));
  342. /* check for corruption                                         */
  343. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  344. return DE_MCBDESTRY;
  345. /* check for wrong allocation                                   */
  346. if(size > p -> m_size)
  347. {
  348. REG UCOUNT delta;
  349. if (p -> m_type == MCB_LAST)
  350. {      
  351.     if (maxSize) *maxSize = p -> m_size + q -> m_size;
  352.     return DE_NOMEM;
  353. }
  354. /* make q a pointer to the next block                   */
  355. q = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  356. /* check for corruption                                         */
  357. if(q -> m_type != MCB_NORMAL && q -> m_type != MCB_LAST)
  358.     return DE_MCBDESTRY;
  359. /* if next mcb is not free, error no memory             */
  360. if(q -> m_psp != FREE_PSP)
  361. {        
  362. if (maxSize) *maxSize = p -> m_size;
  363. return DE_NOMEM;
  364. }
  365. /* reduce the size of q and add difference to p         */
  366. /* but check that q is big enough first                 */
  367. delta = size - p -> m_size;
  368.  
  369. if(q -> m_size < delta)
  370. {        
  371. if (maxSize) *maxSize = p -> m_size + q -> m_size;
  372. return DE_NOMEM;
  373. }
  374. q -> m_size -= delta;
  375. p -> m_size += delta;
  376. /* Now go back and adjust q, we'll make p new q         */
  377. p = MK_FP(far2para((VOID FAR *)q) + delta, 0);
  378. p -> m_type = q -> m_type;
  379. p -> m_psp  = q -> m_psp;
  380. p -> m_size = q -> m_size;
  381. for(i = 0; i < 8; i++)
  382.     p -> m_name[i] = q -> m_name[i];
  383. /* and finished                                         */
  384. return SUCCESS;
  385. }
  386. /* else, shrink it down                                         */
  387. else if(size < p -> m_size)
  388. {
  389. /* make q a pointer to the new next block               */
  390. q = MK_FP(far2para((VOID FAR *)p) + size + 1, 0);
  391. /* reduce the size of p and add difference to q         */
  392. q -> m_type = p -> m_type;
  393. q -> m_size = p -> m_size - size - 1;
  394. p -> m_size = size;
  395. /* Make certian the old psp is not last (if it was)     */
  396. p -> m_type = MCB_NORMAL;
  397. /* Mark the mcb as free so that we can later    */
  398. /* merge with other surrounding free mcb's      */
  399. q -> m_psp = FREE_PSP;
  400. for(i = 0; i < 8; i++)
  401. q -> m_name[i] = '';
  402. /* now free it so that we have a complete block */
  403. return DosMemFree(far2para((VOID FAR *)q));
  404. }
  405. /* otherwise, its a no-op                                       */
  406. else
  407. return SUCCESS;
  408. }
  409. COUNT 
  410. DosMemCheck (void)
  411. {
  412. REG mcb FAR *p;
  413. /* Initialize                                           */
  414. p = (mcb FAR *)(MK_FP(first_mcb, 0));
  415. /* Search through memory blocks                         */
  416. for( ; ; )
  417. {
  418. /* check for corruption                         */
  419. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  420. return DE_MCBDESTRY;
  421. /* not corrupted - if last we're OK!            */
  422. if(p -> m_type == MCB_LAST)
  423. return SUCCESS;
  424. /* not corrupted - but not end, bump the pointer */
  425. else if(p -> m_type != MCB_LAST)
  426. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  427. /* totally lost - bad exit                      */
  428. else
  429. return DE_MCBDESTRY;
  430. }
  431. }
  432. COUNT 
  433. FreeProcessMem (UWORD ps)
  434. {
  435. mcb FAR *p;
  436. /* Initialize                                           */
  437. p = (mcb FAR *)(MK_FP(first_mcb, 0));
  438. /* Search through memory blocks                         */
  439. for( ; ; )
  440. {
  441. /* check for corruption                         */
  442. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  443. return DE_MCBDESTRY;
  444. if(p -> m_psp == ps) 
  445. DosMemFree( FP_SEG(p) );
  446. /* not corrupted - if last we're OK!            */
  447. if(p -> m_type == MCB_LAST) break;
  448. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  449. }
  450. return SUCCESS;
  451. }
  452. COUNT
  453. DosGetLargestBlock(UWORD FAR *block)
  454. {
  455. UWORD sz = 0;
  456. mcb FAR *p;
  457. *block = sz;
  458. /* Initialize                                           */
  459. p = (mcb FAR *)(MK_FP(first_mcb, 0));
  460. /* Search through memory blocks                         */
  461. for( ; ; )
  462. {
  463. /* check for corruption                         */
  464. if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
  465. return DE_MCBDESTRY;
  466. if (p -> m_psp == FREE_PSP && p -> m_size > sz)
  467.     sz = p -> m_size;
  468. /* not corrupted - if last we're OK!            */
  469. if(p -> m_type == MCB_LAST) break;
  470. p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
  471. }
  472. *block = sz;
  473. return SUCCESS;
  474. }
  475. VOID 
  476. show_chain (void)
  477. {
  478. mcb FAR *p = (mcb FAR *)(MK_FP(first_mcb, 0));
  479. for(;;)
  480. {
  481. mcb_print(p);
  482. if(p -> m_type == MCB_LAST || p -> m_type != MCB_NORMAL)
  483. return;
  484. else
  485. p = (mcb FAR *)(MK_FP(far2para((VOID FAR *)p)+p -> m_size+1,0));
  486. }
  487. }
  488. VOID 
  489. mcb_print (mcb FAR *mcbp)
  490. {
  491. static BYTE buff[9];
  492. VOID _fmemcpy();
  493. _fmemcpy((BYTE FAR *)buff, (BYTE FAR *)(mcbp -> m_name), 8);
  494. buff[8] = '';
  495. printf("%04x:%04x -> |%s| m_type = 0x%02x; m_psp = 0x%04x; m_size = 0x%04xn",
  496. FP_SEG(mcbp),
  497. FP_OFF(mcbp),
  498. *buff == '' ? "*NO-ID*" : buff,
  499. mcbp -> m_type,
  500. mcbp -> m_psp,
  501. mcbp -> m_size);
  502. }
  503. VOID _fmemcpy(BYTE FAR *d, BYTE FAR *s, REG COUNT n)
  504. {
  505. while(n--)
  506.       *d++ = *s++;
  507. }
  508. #endif