home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 612b.lha / Bovs_v1.0 / MemMan / MemMan.asm < prev    next >
Assembly Source File  |  1992-02-19  |  8KB  |  283 lines

  1. ********************************************************************************
  2. *
  3. *                                  MemMan
  4. *                                Version 3.0
  5. *                            Low-Memory Manager
  6. *                       Copyright 1992 Bryan Ford
  7. *               See MemMan.doc for distribution requirements
  8. *
  9. ********************************************************************************
  10. * $Id$
  11. * Assemble with A68k version >2.71.
  12.  
  13.         include "exec/types.i"
  14.         include "exec/lists.i"
  15.         include "exec/ables.i"
  16.         include "exec/memory.i"
  17.         include "exec/libraries.i"
  18.         include "exec/semaphores.i"
  19.         include "exec/funcdef.i"
  20.         include "exec/exec_lib.i"
  21.         include "bry/macros.i"
  22.         include "bry/memman.i"
  23.  
  24. _intena equ     $dff09a
  25.  
  26.  STRUCTURE      MemManSem,SS_SIZE       ; SignalSemaphore
  27.         UBYTE   mms_MemCrunch           ; Flag: we're currently having a memory crunch
  28.         BYTE    mms_pad
  29.         ULONG   mms_AppCount            ; Number of apps using MemMan now
  30.         STRUCT  mms_MMList,MLH_SIZE     ; List we link MMNodes onto
  31.         LABEL   mms_Code                ; Copied MemMan library code
  32.         ; Structure is continued farther down... (hehe)
  33.  
  34.         code    text
  35.  
  36.         xdef    MMInit,MMFinish,MMAddNode,MMRemNode
  37.         xdef    _MMInit,_MMFinish,_MMAddNode,_MMRemNode
  38.  
  39. * This code is copied into the global MemManSem structure.
  40. * The first six bytes are overwritten with a JMP instruction
  41. * whenever MemMan is not in use.
  42. * Immediately after that is the old AllocMem vector
  43. * (the last part of the JSR instruction).
  44. * Yup, self-modifying code - isn't it beautiful? :-)
  45. * This makes each AllocMem() call slightly faster and should be fine if we
  46. * are very careful of caching (which we are).  Since the only self-modifying
  47. * code we use is in MEMF_PUBLIC memory, there should be no virtual or protected
  48. * memory problems either.
  49. codest:
  50.         movem.l d0/d1,-(sp)             ; Save registers (4 bytes)
  51.  
  52. jsrinst:
  53.         jsr     $12345678               ; Call regular AllocMem() (2 + 4 bytes)
  54.         tst.l   d0
  55.         bz.b    \failed
  56.  
  57. \out
  58.         addq    #8,sp                   ; Succeeded on the first try
  59.         rts
  60.  
  61. \failed:
  62.         cmp.b   codest-mms_Code+mms_MemCrunch(pc),d0    ; Avoid recursion from GetRidFuncs
  63.         bz.b    \out
  64.  
  65.         movem.l a2-a3,-(sp)
  66.  
  67.         DISABLE a0      ; AllocMem only requires FORBID, but the MMList requires DISABLE
  68.  
  69.         lea     codest-mms_Code+mms_MemCrunch(pc),a0
  70.         st.b    (a0)
  71.  
  72.         move.l  codest-mms_Code+mms_MMList+LH_HEAD(pc),a2
  73.         move.l  jsrinst+2(pc),a3
  74.  
  75. \retry:
  76.         move.l  LN_SUCC(a2),d1          ; Traverse the list forwards
  77.         bz.s    \fin                    ; (kill HIGHEST priority nodes first)
  78.  
  79.         move.l  mmn_GetRidFunc(a2),a1   ; Call the GetRidFunc
  80.         move.l  mmn_GetRidData(a2),a0
  81.         move.l  d1,a2                   ; Find next node BEFORE call
  82.         movem.l 8(sp),d0/d1
  83.         jsr     (a1)
  84.         tst.l   d0
  85.         bz.b    \retry
  86.  
  87.         movem.l 8(sp),d0/d1             ; Try allocating again
  88.         jsr     (a3)
  89.         tst.l   d0
  90.         bz.b    \retry
  91.  
  92. \fin:
  93.         move.l  a0,-(sp)                ; Some nasty apps rely on d1/a0/a1...
  94.  
  95.         lea     codest-mms_Code+mms_MemCrunch(pc),a0
  96.         clr.b   (a0)
  97.  
  98.         ENABLE  a0
  99.  
  100.         movem.l (sp)+,a0/a2-a3
  101.         addq.l  #8,sp                   ; Pop AllocMem args off stack
  102.         rts
  103.  
  104. semname:
  105.         dc.b    "MemMan21",0
  106.         ds.w    0
  107.  
  108. codefin:
  109.  
  110.         ; Continuation of MemManSem structure (now that we know the code size)
  111.         STRUCT  mms_Code_def2,(codefin-codest)
  112.         LABEL   mms_SIZEOF
  113.  
  114. *** Initialize MemMan - patches AllocMem()
  115. * Returns:
  116. * d0 = Nonzero if successful, zero if failed
  117. MMInit:
  118. _MMInit:
  119.         apush
  120.         move.l  4,a6
  121.  
  122.         FORBID
  123.  
  124.         lea     semname(pc),a1          ; See if the semaphore already exists
  125.         jsr     _LVOFindSemaphore(a6)
  126.         move.l  d0,semaphore
  127.         bnz     \oldsem
  128.  
  129. \newsem:
  130.         move.l  #mms_SIZEOF,d0          ; Allocate the public memory block
  131.         move.l  #MEMF_PUBLIC!MEMF_CLEAR,d1
  132.         jsr     _LVOAllocMem(a6)
  133.         move.l  d0,semaphore
  134.         bz      \outnomem
  135.         move.l  d0,a5
  136.  
  137.         lea     mms_MMList(a5),a0       ; Initialize the data area
  138.         NEWLIST a0
  139.         move.w  #1,mms_AppCount(a5)
  140.         lea     mms_Code+(semname-codest)(a5),a0
  141.         move.l  a0,LN_NAME(a5)
  142.  
  143.         lea     codest(pc),a0           ; Copy the public code
  144.         lea     mms_Code(a5),a1
  145.         move.l  #codefin-codest,d0
  146.         jsr     _LVOCopyMem(a6)
  147.  
  148.         move.l  a6,a1                   ; SetFunction AllocMem()
  149.         lea     mms_Code(a5),a0
  150.         move.l  a0,d0
  151.         movea.w #_LVOAllocMem,a0
  152.         jsr     _LVOSetFunction(a6)
  153.  
  154.         move.l  d0,mms_Code+(jsrinst-codest)+2(a5)      ; Set JSR vector
  155.  
  156.         cmpi.w  #36,LIB_VERSION(a6)     ; Clear the cache after setting vector
  157.         blo.b   \newsemcc
  158.         jsr     _LVOCacheClearU(a6)
  159. \newsemcc:
  160.  
  161.         move.l  a5,a1                   ; Add to system semaphore list
  162.         move.l  a5,a0                   ; BUUUUUUUUUUUUUUUG in 1.3!!!
  163.         jsr     _LVOAddSemaphore(a6)
  164.  
  165.         bra     \outok
  166.  
  167. \oldsem:                                ; Semaphore was already in memory
  168.         move.l  d0,a5
  169.  
  170.         addq.w  #1,mms_AppCount(a5)
  171.  
  172.         cmp.w   #$4ef9,mms_Code(a5)     ; See if we have to reactivate the code
  173.         bne.s   \codefine
  174.  
  175.         move.l  codest(pc),mms_Code(a5) ; Restore the first six bytes
  176.         move.w  codest+4(pc),mms_Code+4(a5) ; No more or we'll trash the vector
  177.  
  178.         cmpi.w  #36,LIB_VERSION(a6)     ; Clear the cache after changing code
  179.         blo.s   \oldsemcc
  180.         jsr     _LVOCacheClearU(a6)
  181. \oldsemcc:
  182. \codefine:
  183. \outok:
  184.         lea     mms_MMList(a5),a0
  185.         move.l  a0,mmlist
  186.  
  187.         PERMIT
  188.  
  189.         moveq   #1,d0
  190. \out:
  191.         apop
  192.         rts
  193.  
  194. \outnomem
  195.         PERMIT
  196.         moveq   #0,d0
  197.         bra.b   \out
  198.  
  199. *** Uninstall our application from the memory manager
  200. MMFinish:
  201. _MMFinish:
  202.         apush
  203.         move.l  4,a6
  204.  
  205.         move.l  semaphore,d0            ; Never successfully initialized?
  206.         bz      \out
  207.         move.l  d0,a5
  208.  
  209.         FORBID
  210.  
  211.         subq.w  #1,mms_AppCount(a5)
  212.         bnz.s   \otherapps
  213.  
  214.         move.w  #$4ef9,mms_Code(a5)     ; Quick bounce with a JMP instruction
  215.         move.l  mms_Code+(jsrinst-codest)+2(a5),mms_Code+2(a5)
  216.  
  217.         cmpi.w  #36,LIB_VERSION(a6)     ; Clear the cache after changing code
  218.         blo.s   \cc
  219.         jsr     _LVOCacheClearU(a6)
  220. \cc:
  221.  
  222. \otherapps:
  223.  
  224.         PERMIT
  225.  
  226.         clr.l   semaphore               ; Safety
  227.  
  228. \out:
  229.         apop
  230.         rts
  231.  
  232.  
  233. *** Add an MMNode (if it wasn't already on the MMList)
  234. * a1 = Pointer to MMNode
  235. MMAddNode:
  236. _MMAddNode:
  237.         DISABLE a0
  238.  
  239.         cmp.b   #MMNT_LINKED,LN_TYPE(a1)        ; Don't add a node twice
  240.         bne.b   mmadd
  241.  
  242.         ENABLE  a0,NOFETCH
  243.         rts
  244.  
  245. mmadd
  246.         move.l  a6,-(sp)
  247.         move.l  a0,a6
  248.  
  249.         move.b  #MMNT_LINKED,LN_TYPE(a1)        ; Mark it as added
  250.  
  251.         move.l  mmlist,a0       ; Add it to the global list in prioritized order
  252.         jsr     _LVOEnqueue(a6)
  253.  
  254.         ENABLE
  255.         move.l  (sp)+,a6
  256.         rts
  257.  
  258.  
  259. *** Remove an MMNode (only if it was on the MMList)
  260. * a1 = Pointer to MMNode
  261. MMRemNode:
  262. _MMRemNode:
  263.         DISABLE a0
  264.         cmp.b   #MMNT_LINKED,LN_TYPE(a1)        ; Don't remove unless it was added
  265.         beq.b   mmremove
  266.         ENABLE  a0,NOFETCH
  267.         rts
  268.  
  269. mmremove
  270.         clr.b   LN_TYPE(a1)     ; Mark it as not added
  271.  
  272.         REMOVE                  ; Remove it from the public MMList
  273.  
  274.         ENABLE  a0
  275.         rts
  276.  
  277.         bss     __MERGED
  278.  
  279. semaphore       ds.l    1               ; Pointer to public semaphore
  280. mmlist          ds.l    1               ; Points to mms_MMList in MemManSem
  281.  
  282.         end
  283.