home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 581a.lha / MemMan_v2.0 / MemMan.asm < prev    next >
Assembly Source File  |  1991-12-04  |  9KB  |  301 lines

  1. ********************************************************************************
  2. *
  3. *                                  MemMan
  4. *                                Version 2.0
  5. *                            Low-Memory manager
  6. *                       Copyright (C) 1991 Bryan Ford
  7. *
  8. *
  9. * This source code may be freely distributed as long as it is complete (see
  10. * MemMan.doc for the required files), all of the files are unmodified, and no
  11. * charge is made for such distribution other than a small fee to cover the
  12. * cost of copying (no profit may be made through distribution of this
  13. * program).  You may modify this code for your own personal use, but you may
  14. * not distribute modified versions.  (Just send your improvements back to me
  15. * - I'll incorporate them in the master, of course giving credit to you, and
  16. * that way we won't have hundreds of different versions floating around.)
  17. *
  18. * You may use the object code derived from this (or your own modified version
  19. * of this) source code in your own public domain, freeware, or shareware
  20. * programs (programs that are distributed on similar terms to this source
  21. * code), as long as you mention the use of MemMan and its author (me)
  22. * somewhere in your documentation.  You do not need to obtain any kind of
  23. * license in this case.
  24. *
  25. * If you want to distribute MemMan (or any modified variation of it), in
  26. * either source or object form, with a commercial package, you must obtain my
  27. * written permission.  (Don't worry, I'm not starving at this point - a
  28. * license will be very cheap, most likely consisting simply of a copy of the
  29. * program you're using it in.)
  30. *
  31. ********************************************************************************
  32. *
  33. * Thanks to Michael Sinz of Commodore for his valuable suggestions for improving
  34. * this code and making it more compatible with future versions of the OS.
  35. *
  36. * Also, special thanks to David Le Blanc for the library version and the test
  37. * program.
  38. *
  39. ********************************************************************************
  40. *
  41. * Assemble with A68k version >2.71.
  42. *
  43.  
  44.         include "exec/types.i"
  45.         include "exec/lists.i"
  46.         include "exec/ables.i"
  47.         include "exec/memory.i"
  48.         include "exec/libraries.i"
  49.         include "exec/semaphores.i"
  50.         include "exec/funcdef.i"
  51.         include "exec/exec_lib.i"
  52.         include "bry/macros.i"
  53.         include "bry/memman.i"
  54.  
  55.  STRUCTURE      MemManSem,SS_SIZE       ; SignalSemaphore
  56.         UWORD   mms_AppCount            ; Number of apps using MemMan now
  57.         STRUCT  mms_MMList,MLH_SIZE     ; List we link MMNodes onto
  58.         LABEL   mms_Code                ; Copied MemMan library code
  59.         ; Structure is continued farther down... (hehe)
  60.  
  61.         code    text
  62.  
  63.         xdef    MMInit,MMFinish,MMAddNode,MMRemNode
  64.         xdef    _MMInit,_MMFinish,_MMAddNode,_MMRemNode
  65.  
  66. * This code is copied into the global MemManSem structure.
  67. * The first six bytes are overwritten with a JMP instruction
  68. * whenever MemMan is not in use.
  69. * Immediately after that is the old AllocMem vector
  70. * (last part of the JSR instruction).
  71. * Yup, self-modifying code - isn't it beautiful? :-)
  72. * This makes each AllocMem() call slightly faster and should be fine if we
  73. * are very careful of caching (which we are).  Since the only self-modifying
  74. * code we use is in MEMF_PUBLIC memory, there should be no virtual or protected
  75. * memory problems either.
  76. codest:
  77.         push    d0/d1                   ; Save registers (4 bytes of code)
  78.  
  79. jsrinst:
  80.         jsr     $12345678               ; Call regular AllocMem() (2 + 4 bytes)
  81.         tst.l   d0
  82.         bz.s    \failed
  83.  
  84.         addq.l  #8,sp                   ; Succeeded on the first try
  85.         rts
  86.  
  87. \failed:
  88.         push    a2-a3
  89.         move.l  codest-mms_Code+mms_MMList+LH_HEAD(pc),a2
  90.         move.l  jsrinst+2(pc),a3
  91.  
  92.         FORBID
  93.  
  94. \retry:
  95.         move.l  LN_SUCC(a2),d1          ; Traverse the list forwards
  96.         bz.s    \fin                    ; (kill HIGHEST priority nodes first)
  97.  
  98.         move.l  mmn_GetRidFunc(a2),a1   ; Call the GetRidFunc
  99.         move.l  mmn_GetRidData(a2),a0
  100.         move.l  d1,a2                   ; Find next node BEFORE call
  101.         movem.l 8(sp),d0/d1
  102.         jsr     (a1)
  103.  
  104.         movem.l 8(sp),d0/d1             ; Try allocating again
  105.         jsr.l   (a3)
  106.         tst.l   d0
  107.         bz.s    \retry
  108.  
  109. \fin:
  110.         push    d0-d1/a0-a1             ; Some nasty apps rely on d1/a0/a1...
  111.         PERMIT
  112.         pop     d0-d1/a0-a1/a2-a3
  113.         addq.l  #8,sp                   ; Pop AllocMem args off stack
  114.         rts
  115.  
  116. semname:
  117.         dc.b    "MemMan2",0
  118.         ds.w    0
  119.  
  120. codefin:
  121.  
  122.         ; Continuation of MemManSem structure (now that we know the code size)
  123.         STRUCT  mms_Code_def2,(codefin-codest)
  124.         LABEL   mms_SIZEOF
  125.  
  126. *** Initialize MemMan - patches AllocMem()
  127. * Returns:
  128. * d0 = Nonzero if successful, zero if failed
  129. MMInit:
  130. _MMInit:
  131.         apush
  132.         move.l  4,a6
  133.  
  134.         lea     semname(pc),a1          ; See if the semaphore already exists
  135.         jsr     _LVOFindSemaphore(a6)
  136.         move.l  d0,semaphore
  137.         bnz     \oldsem
  138.  
  139.         ; There is the VERY slight chance we could get two MemMan semaphores
  140.         ; at once.  Who cares?  Nothing terrible would happen anyway.
  141. \newsem:
  142.         move.l  #mms_SIZEOF,d0          ; Allocate the public memory block
  143.         move.l  #MEMF_PUBLIC!MEMF_CLEAR,d1
  144.         jsr     _LVOAllocMem(a6)
  145.         move.l  d0,semaphore
  146.         bz      \out
  147.         move.l  d0,a5
  148.  
  149.         lea     mms_MMList(a5),a0       ; Initialize the data area
  150.         NEWLIST a0
  151.         move.w  #1,mms_AppCount(a5)
  152.         lea     mms_Code+(semname-codest)(a5),a0
  153.         move.l  a0,LN_NAME(a5)
  154.  
  155.         lea     codest(pc),a0           ; Copy the public code
  156.         lea     mms_Code(a5),a1
  157.         move.l  #codefin-codest,d0
  158.         jsr     _LVOCopyMem(a6)
  159.  
  160.         FORBID                          ; No AllocMem()s in here please
  161.  
  162.         move.l  a6,a1                   ; SetFunction AllocMem()
  163.         lea     mms_Code(a5),a0
  164.         move.l  a0,d0
  165.         movea.w #_LVOAllocMem,a0
  166.         jsr     _LVOSetFunction(a6)
  167.  
  168.         move.l  d0,mms_Code+(jsrinst-codest)+2(a5)      ; Set JSR vector
  169.  
  170.         cmpi.w  #36,LIB_VERSION(a6)     ; Clear the cache after setting vector
  171.         blo.s   \newsemcc
  172.         jsr     _LVOCacheClearU(a6)
  173. \newsemcc:
  174.         PERMIT
  175.  
  176.         move.l  a5,a1                   ; Add to system semaphore list
  177.         move.l  a5,a0                   ; BUUUUUUUUUUUUUUUG in 1.3!!!
  178.         jsr     _LVOAddSemaphore(a6)
  179.  
  180.         bra     \outok
  181.  
  182. \oldsem:                                ; Semaphore was already in memory
  183.         move.l  d0,a5
  184.  
  185.         move.l  d0,a0
  186.         jsr     _LVOObtainSemaphore(a6)
  187.  
  188.         addq.w  #1,mms_AppCount(a5)
  189.  
  190.         cmp.w   #$4ef9,mms_Code(a5)     ; See if we have to reactivate the code
  191.         bne.s   \codefine
  192.  
  193.         FORBID                          ; No AllocMem()s while we change code
  194.  
  195.         move.l  codest(pc),mms_Code(a5) ; Restore first six bytes
  196.         move.w  codest+4(pc),mms_Code+4(a5) ; No more or we'll trash the vector
  197.  
  198.         cmpi.w  #36,LIB_VERSION(a6)     ; Clear the cache after changing code
  199.         blo.s   \oldsemcc
  200.         jsr     _LVOCacheClearU(a6)
  201. \oldsemcc:
  202.  
  203.         PERMIT
  204. \codefine:
  205.  
  206.         move.l  a5,a0
  207.         jsr     _LVOReleaseSemaphore(a6)
  208. \outok:
  209.         lea     mms_MMList(a5),a0
  210.         move.l  a0,mmlist
  211.  
  212.         moveq   #1,d0
  213. \out:
  214.         apop
  215.         rts
  216.  
  217.  
  218. *** Uninstall our application from the memory manager
  219. MMFinish:
  220. _MMFinish:
  221.         apush
  222.         move.l  4,a6
  223.  
  224.         move.l  semaphore,d0            ; Never successfully initialized?
  225.         bz      \out
  226.         move.l  d0,a5
  227.  
  228.         move.l  a5,a0
  229.         jsr     _LVOObtainSemaphore(a6)
  230.  
  231.         subq.w  #1,mms_AppCount(a5)
  232.         bnz.s   \otherapps
  233.  
  234.         FORBID                          ; No AllocMem()s while we change the code
  235.  
  236.         move.w  #$4ef9,mms_Code(a5)     ; Quick bounce with a JMP instruction
  237.         move.l  mms_Code+(jsrinst-codest)+2(a5),mms_Code+2(a5)
  238.  
  239.         cmpi.w  #36,LIB_VERSION(a6)     ; Clear the cache after changing code
  240.         blo.s   \cc
  241.         jsr     _LVOCacheClearU(a6)
  242. \cc:
  243.  
  244.         PERMIT
  245. \otherapps:
  246.  
  247.         move.l  a5,a0
  248.         jsr     _LVOReleaseSemaphore(a6)
  249.  
  250.         clr.l   semaphore               ; Safety
  251.  
  252. \out:
  253.         apop
  254.         rts
  255.  
  256.  
  257. *** Add an MMNode (if it wasn't already on the MMList)
  258. * a1 = Pointer to MMNode
  259. MMAddNode:
  260. _MMAddNode:
  261.         cmp.b   #MMNT_LINKED,LN_TYPE(a1)        ; Don't add a node twice
  262.         beq.s   9$
  263.  
  264.         mb      #MMNT_LINKED,LN_TYPE(a1)        ; Mark it as added
  265.  
  266.         push    a6              ; Add it to the global list in prioritized order
  267.         move.l  4,a6
  268.         move.l  mmlist,a0
  269.         FORBID
  270.         jsr     _LVOEnqueue(a6)
  271.         PERMIT
  272.         pop     a6
  273.  
  274. 9$      rts
  275.  
  276.  
  277. *** Remove an MMNode (only if it was on the MMList)
  278. * a1 = Pointer to MMNode
  279. MMRemNode:
  280. _MMRemNode:
  281.         cmp.b   #MMNT_LINKED,LN_TYPE(a1)        ; Don't remove unless it was added
  282.         bne.s   9$
  283.  
  284.         clr.b   LN_TYPE(a1)     ; Mark it as not added
  285.  
  286.         push    a6              ; Remove it from the public MMList
  287.         move.l  4,a6
  288.         FORBID
  289.         REMOVE
  290.         PERMIT
  291.         pop     a6
  292.  
  293. 9$      rts
  294.  
  295.         bss     __MERGED
  296.  
  297. semaphore       ds.l    1               ; Pointer to public semaphore
  298. mmlist          ds.l    1               ; Points to mms_MMList in MemManSem
  299.  
  300.         end
  301.