home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / musik / MIDIFP21 / SOURCES / MY_LIB / ACS_PLUS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-24  |  10.7 KB  |  465 lines

  1. /**************************************************************
  2. *
  3. *                ACS_PLUS.C
  4. *
  5. **************************************************************/
  6.  
  7. #include <stdio.h> 
  8. #include <string.h>
  9. #include <stdlib.h> /* because of ltoa(), ... */
  10. #include <tos.h>    /* because of Fforce(), ... */
  11. #include <acs.h>
  12. #include <acs_plus.pif>
  13. #include "acs_plus.h"
  14. #include "acs_plus.ah" 
  15. #include <messages.pif>
  16.  
  17.  
  18. /**************************************************************
  19. *
  20. *                memory management
  21. *
  22. **************************************************************/
  23.  
  24. /*** global variable, used to point to symptom data for debug_mem ***/ 
  25.  
  26. char *memory_symptom ;
  27.  
  28.  
  29. /*** global variable for recording memory management operations ***/
  30.  
  31. #define MAX_OPERATIONS 64
  32.  
  33. struct OPERATION
  34. {
  35.     enum {Memory, String, Object, Window} type ;
  36.     long ptr ;
  37.     long size ;
  38. } ;
  39.  
  40. static struct OPERATION operation[MAX_OPERATIONS] ;
  41. static char i = 0 ;
  42.  
  43. /*** own memory management ***/
  44.  
  45. #define BLOCK_SIZE 0x10000L  /* size to be allocated in 1 one block */
  46. #define MIN_BYTES  4         /* minimum length of last section */
  47.  
  48. struct BH /* block header for blocks of allocated memory */
  49. { /* sizeof(BH) must be a multiple of 4 */
  50.     long      size ;   /* total size of block */
  51.     long      free ;   /* net free size */
  52.     struct BH *next ;  /* pointer to next list element */
  53.     long      cs ;     /* checksum for this header */
  54. *bh_first = NULL ; /* pointer to first list element */ ;
  55.  
  56. struct SH /* section header for memory sections inside blocks */
  57. { /* sizeof(SH) must be a multiple of 4 */
  58.     long size ;   /* net size of following section */
  59.     int  FREE ;   /* TRUE = next section is free */
  60.     int  cs ;     /* checksum for this header */
  61. } ;
  62.  
  63.  
  64.  
  65. long block_cs(struct BH *bh)
  66. { return ~( bh->size + bh->free + (long)(bh->next) ) ; }
  67.  
  68. int section_cs(struct SH *sh)
  69. { return ~( (int)sh->size + sh->FREE ) ; }
  70.  
  71.  
  72. void *new_block(long blocksize, long size) 
  73. {
  74. struct BH *bh ;
  75. struct SH *sh, *sh_next ;
  76.  
  77.     /*** allocate memory ***/
  78.     bh = (struct BH *)Ax_malloc(blocksize) ;
  79.     if (bh == NULL) { alert_str(OUT_OF_MEMORY, "") ; return NULL ; }
  80.     
  81.     /*** init headers ***/
  82.     bh->next = bh_first ; bh_first = bh ; /* chain in */
  83.     bh->size = blocksize ;
  84.     sh = (struct SH *)(bh + 1) ;
  85.     sh->FREE = FALSE ;
  86.     
  87.     /*** init 1 header for free section ***/
  88.     sh->size = blocksize - sizeof(*bh) - sizeof(*sh) ;
  89.     bh->free = 0 ;
  90.     if (size + sizeof(*bh) + (sizeof(*sh)<<1) + MIN_BYTES <= blocksize)
  91.     {
  92.         /*** init 1 more header for free section ***/
  93.         sh->size = size ;
  94.         sh_next = (struct SH *)((long)(sh + 1) + sh->size) ;
  95.         sh_next->FREE = TRUE ;
  96.         sh_next->size = blocksize - size - sizeof(*bh) - (sizeof(*sh)<<1) ;
  97.         sh_next->cs = section_cs(sh_next) ;
  98.         bh->free = sh_next->size ;
  99.     }
  100.     sh->cs = section_cs(sh) ;
  101.     bh->cs = block_cs(bh) ;
  102.     
  103.     /*** return pointer to user section ***/
  104.     return (void *)(sh + 1) ;
  105. }
  106.  
  107.  
  108. void *Allocate(long size)
  109. struct SH *sh, *sh_new ;
  110. struct BH *bh ;
  111. char address[30] ;
  112.  
  113.     /*** round up size to a multiple of 4 ***/
  114.     size = (size + 3) & 0xfffffffcL ;
  115.  
  116.     /*** if requested size is big enough, user gets an extra block ***/
  117.     if (size > BLOCK_SIZE / 2) return new_block(size + sizeof(*bh) + sizeof(*sh), size) ;
  118.  
  119.     /*** else: search for a free section inside allocated blocks ***/
  120.     bh = bh_first ;
  121.     while (bh != NULL) 
  122.     {
  123.         if (bh->cs != block_cs(bh)) 
  124.         { 
  125.             alert_str(BLOCK_DESTROYED, ltoa((long)bh, address, 16)) ; 
  126.             return NULL ; 
  127.         }
  128.         if (bh->free >= size)
  129.         {
  130.             /*** search this block for a free section ***/
  131.             sh = (struct SH *)(bh + 1) ;
  132.             while ( (long)sh < (long)bh + bh->size )  
  133.             {
  134.                 if (sh->cs != section_cs(sh))
  135.                 {
  136.                     alert_str(SECTION_DESTROYED, ltoa((long)sh, address, 16)) ;
  137.                     return NULL ;
  138.                 }
  139.                 if (sh->FREE) 
  140.                 {
  141.                     if (sh->size >= size)
  142.                     {
  143.                         /*** allocate section (partly) ***/
  144.                         if (sh->size >= size + sizeof(*sh) + MIN_BYTES )
  145.                         {
  146.                             /*** create new section header ***/
  147.                             sh_new = (struct SH *)((long)(sh + 1) + size) ;
  148.                             sh_new->FREE = TRUE ;
  149.                             sh_new->size = sh->size - size - sizeof(*sh_new) ;
  150.                             sh_new->cs = section_cs(sh_new) ;
  151.     
  152.                             /*** update block header ***/
  153.                             bh->free -= sizeof(*sh_new) ;
  154.         
  155.                             /*** update section header ***/
  156.                             sh->size = size ;
  157.                         }
  158.                         sh->FREE = FALSE ;
  159.                         sh->cs = section_cs(sh) ;
  160.                         bh->free -= sh->size ;
  161.                         bh->cs = block_cs(bh) ;
  162.                         return (void *)(sh + 1) ;
  163.                     }
  164.                 } /* if section is free */
  165.                 sh = (struct SH *)( (long)(sh + 1) + sh->size ) ;
  166.             }
  167.         } /* if enough free memory in this block */
  168.         bh = bh->next ;
  169.     } 
  170.     /*** nothing suitable found up to now -> allocate new block ***/
  171.     return new_block(BLOCK_SIZE, size) ;
  172. }
  173.  
  174.  
  175. void Free(void *ptr)
  176. {
  177. struct BH *bh_prev, *bh ;
  178. struct SH *sh, *sh_next, *sh_prev ;
  179. char address[30] ;
  180.  
  181.     bh_prev = NULL ;
  182.     bh = bh_first ;
  183.     while (bh != NULL) 
  184.     {
  185.         if (bh->cs != block_cs(bh)) 
  186.         { 
  187.             alert_str(BLOCK_DESTROYED, ltoa((long)bh, address, 16)) ; 
  188.             return ; 
  189.         }
  190.         if ( ((long)ptr >= (long)bh + sizeof(*bh) + sizeof(*sh))
  191.             && ((long)ptr < (long)bh + bh->size) )
  192.         {
  193.             /*** memory to be freed lies in this block ***/
  194.             sh = (struct SH *)(bh + 1) ; sh_prev = sh ;
  195.             while ( (long)sh < (long)bh + bh->size ) 
  196.             {
  197.                 if (sh->cs != section_cs(sh))
  198.                 {
  199.                     alert_str(SECTION_DESTROYED, ltoa((long)sh, address, 16)) ;
  200.                     return ;
  201.                 }
  202.                 if ((void *)(sh + 1) == ptr)
  203.                 {
  204.                     /*** free section ***/
  205.                     sh->FREE = TRUE ;
  206.                     bh->free += sh->size ;
  207.                     sh_next = (struct SH *)((long)(sh + 1) + sh->size) ;
  208.                     if ((long)sh_next + sizeof(*sh_next) + MIN_BYTES <= (long)bh + bh->size )
  209.                     {
  210.                         if (sh_next->cs != section_cs(sh_next))
  211.                         {
  212.                             alert_str(SECTION_DESTROYED, ltoa((long)sh, address, 16)) ;
  213.                             return ;
  214.                         }
  215.                         if (sh_next->FREE)
  216.                         {
  217.                             /*** put together both free sections ***/
  218.                             sh->size += (sizeof(*sh_next) + sh_next->size) ;
  219.  
  220.                             /*** update block header ***/
  221.                             bh->free += sizeof(*sh_next) ;
  222.                         }
  223.                     }
  224.                     sh->cs = section_cs(sh) ;
  225.                     if ((sh_prev->FREE) && (sh_prev != sh))
  226.                     {
  227.                         /*** put together both free sections ***/
  228.                         sh_prev->size += (sizeof(*sh) + sh->size) ;
  229.                         sh_prev->cs = section_cs(sh_prev) ;
  230.         
  231.                         /*** update block header ***/
  232.                         bh->free += sizeof(*sh) ;
  233.                     }
  234.                     bh->cs = block_cs(bh) ;
  235.                     if (bh->free + sizeof(*bh) + sizeof(*sh) == bh->size)
  236.                     {
  237.                         /*** block is empty, it can be freed ***/
  238.                         if (bh_prev == NULL) bh_first = bh->next ;
  239.                         else
  240.                         {
  241.                             bh_prev->next = bh->next ;
  242.                             bh_prev->cs = block_cs(bh_prev) ;
  243.                         }
  244.                         Ax_free(bh) ;
  245.                     }
  246.                 return ;
  247.                 }
  248.                 sh_prev = sh ;
  249.                 sh = (struct SH *)( (long)(sh + 1) + sh->size ) ;
  250.             } 
  251.         } /* if inside this block */
  252.         bh_prev = bh ;
  253.         bh = bh->next ;
  254.     } 
  255.     alert_str(NOT_ALLOCATED, "") ;
  256. }
  257.  
  258.  
  259. void debug_mem (void* defective)
  260. {
  261. char all_symptoms[30] = "" ;
  262.  
  263.     ltoa( (long)defective, all_symptoms, 0x10) ;
  264.     strncat(all_symptoms, " ", 1) ;
  265.     strncat(all_symptoms, memory_symptom, 20) ;
  266.     alert_str(MEMORY_ERROR, all_symptoms) ; 
  267. }
  268.  
  269.  
  270. void *My_shrink(void *memory, long size)
  271. {
  272. void *new_memory ;
  273.  
  274.     /*** free memory if new size shall be 0 ***/
  275.     if (!size) 
  276.     {
  277.         My_free(memory) ;
  278.         return NULL ;
  279.     }
  280.     /*** allocate new memory ***/
  281.     new_memory = My_alloc(size) ;
  282.     if (!new_memory) return memory ; /* not "shrinked" */    
  283.  
  284.     /*** copy old to new ***/
  285.     memcpy(new_memory, memory, size) ;
  286.  
  287.     /*** free old memory ***/
  288.     My_free(memory) ;
  289.  
  290.     /*** return pointer to new memory ***/
  291.     return new_memory ; 
  292. }
  293.  
  294.  
  295. void *My_alloc(long size)
  296. {
  297.     void *ptr = Allocate(size) ;
  298.     if (i < MAX_OPERATIONS)
  299.     {
  300.         operation[i].type = Memory ;
  301.         operation[i].ptr  = (long)ptr ;
  302.         operation[i].size = size ;
  303.         i++ ;
  304.     }
  305.     return ptr ;
  306. }
  307.  
  308. void My_free(void *ptr)
  309. {
  310.     Free(ptr) ;
  311.     if (i < MAX_OPERATIONS)
  312.     {
  313.         operation[i].type = Memory ;
  314.         operation[i].ptr  = (long)ptr ;
  315.         operation[i].size = 0 ;
  316.         i++ ;
  317.     }
  318. }
  319.  
  320.  
  321. char *Myst_create(const char *parent)
  322. {
  323.     char *ptr = Ast_create(parent) ;
  324.     if (i < MAX_OPERATIONS)
  325.     {
  326.         operation[i].type = String ;
  327.         operation[i].ptr  = (long)ptr ;
  328.         operation[i].size = strlen(parent) ;
  329.         i++ ;
  330.     }
  331.     return ptr ;
  332. }
  333.  
  334. void Myst_delete(char *ptr)
  335. {
  336.     Ast_delete(ptr) ;
  337.     if (i < MAX_OPERATIONS)
  338.     {
  339.         operation[i].type = String ;
  340.         operation[i].ptr  = (long)ptr ;
  341.         operation[i].size = 0 ;
  342.         i++ ;
  343.     }
  344. }
  345.  
  346.  
  347. OBJECT *Myob_create(const OBJECT *parent)
  348. {
  349.     OBJECT *ptr = Aob_create(parent) ;
  350.     if (i < MAX_OPERATIONS)
  351.     {
  352.         operation[i].type = Object ;
  353.         operation[i].ptr  = (long)ptr ;
  354.         operation[i].size = sizeof(*ptr) ;
  355.         i++ ;
  356.     }
  357.     return ptr ;
  358. }
  359.  
  360. void Myob_delete(OBJECT *ptr)
  361. {
  362.     Aob_delete(ptr) ;
  363.     if (i < MAX_OPERATIONS)
  364.     {
  365.         operation[i].type = Object ;
  366.         operation[i].ptr  = (long)ptr ;
  367.         operation[i].size = 0 ;
  368.         i++ ;
  369.     }
  370. }
  371.  
  372.  
  373. Awindow *Mywi_create(const Awindow *parent)
  374. {
  375.     Awindow *ptr = Awi_create(parent) ;
  376.     if (i < MAX_OPERATIONS)
  377.     {
  378.         operation[i].type = Window ;
  379.         operation[i].ptr  = (long)ptr ;
  380.         operation[i].size = sizeof(*ptr) ;
  381.         i++ ;
  382.     }
  383.     return ptr ;
  384. }
  385.  
  386. void Mywi_delete(Awindow *ptr)
  387. {
  388.     Awi_delete(ptr) ;
  389.     if (i < MAX_OPERATIONS)
  390.     {
  391.         operation[i].type = Window ;
  392.         operation[i].ptr  = (long)ptr ;
  393.         operation[i].size = 0 ;
  394.         i++ ;
  395.     }
  396. }
  397.  
  398.  
  399. void print_operations(void)
  400. {
  401.     Fforce(1, (int)Fdup(3)) ;
  402.     for (i = 0 ; i < MAX_OPERATIONS ; i++)
  403.     {
  404.         switch (operation[i].type)
  405.         {
  406.             case Memory: printf("Memory %lx", (long)operation[i].ptr) ; break ;
  407.             case String: printf("String %lx", (long)operation[i].ptr) ; break ;
  408.             case Object: printf("Object %lx", (long)operation[i].ptr) ; break ;
  409.             case Window: printf("Window %lx", (long)operation[i].ptr) ; break ;
  410.         }
  411.         printf(" Size %lx \n", operation[i].size) ;
  412.     }
  413.     Fforce(1, (int)Fdup(1)) ;
  414. }
  415.  
  416.  
  417. /**************************************************************
  418. *
  419. *                timer management
  420. *
  421. **************************************************************/
  422.  
  423. static Awindow *waiting_wi = NULL ;
  424. static int rest_time ;
  425.  
  426. int set_timer(Awindow *wi)
  427. {
  428.     if ((!waiting_wi) || (wi == waiting_wi))
  429.     {
  430.         rest_time = 3000 ; /* ms */
  431.         waiting_wi = wi ; /* now timer is running */
  432.         return 0 ;
  433.     }
  434.     else return -1 ;
  435. }
  436.  
  437. void stop_timer(Awindow *wi)
  438. { waiting_wi = NULL ; }
  439.  
  440. static void timer(void)
  441. {
  442. Awindow *buffer_wi ;
  443.  
  444.     if (waiting_wi)
  445.     {
  446.         /*** a job is running */
  447.         rest_time -= ev_mtcount ;
  448.         if (rest_time <= 0)
  449.         {
  450.             /*** timer expired ***/
  451.             buffer_wi = waiting_wi ;
  452.             waiting_wi = NULL ; /* timer is stopped now */
  453.             Awi_sendall(REDRAW, buffer_wi) ;
  454.         }
  455.     }
  456. }
  457.  
  458. void init_time(void)
  459. { ACSblk->ACStimer = timer ; /* replace with own timer procedure */ }
  460.  
  461.  
  462.  
  463.