home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 568a.lha / MemMan / MemMan.asm < prev    next >
Encoding:
Assembly Source File  |  1991-11-08  |  6.9 KB  |  287 lines

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