/*
*********************************************************************************************************
*                                                uC/OS-II
*                                          The Real-Time Kernel
*                                            MEMORY MANAGEMENT
*
*                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
*                                           All Rights Reserved
*
*                                                  V2.00
*
* File : OS_MEM.C
* By   : Jean J. Labrosse
*********************************************************************************************************
*/

#ifndef  OS_MASTER_FILE
#include "includes.h"
#endif

#if OS_MEM_EN && OS_MAX_MEM_PART >= 2
/*
*********************************************************************************************************
*                                             Áö¿ªÀû Àü¿ªº¯¼ö
*********************************************************************************************************
*/

static  OS_MEM      *OSMemFreeList;            /* ¸Þ¸ð¸® ÆÄƼ¼ÇÀÇ ÀÚÀ¯ ¸®½ºÆ®¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ        */
static  OS_MEM       OSMemTbl[OS_MAX_MEM_PART];/* ¸Þ¸ð¸® ÆÄƼ¼Ç °ü¸®ÀÚ°¡ »ç¿ëÇÏ´Â ÀúÀ念¿ª             */
/*$PAGE*/
/*
*********************************************************************************************************
*                                            ¸Þ¸ð¸® ÆÄƼ¼Ç »ý¼º
*
* ¼³¸í        : uC/OS-II°¡ °ü¸®ÇÏ´Â °íÁ¤ Å©±â ¸Þ¸ð¸® ÆÄƼ¼ÇÀ» »ý¼ºÇÑ´Ù.
*
* Àü´ÞÀÎÀÚ    : addr     ¸Þ¸ð¸® ÆÄƼ¼ÇÀÇ ½ÃÀÛ ¾îµå·¹½º.
*
*               nblks    ÆÄƼ¼Ç¿¡¼­ »ý¼ºÇÒ ¸Þ¸ð¸® ºí·Ï ¼ö.
*
*               blksize  °¢ ºí·ÏÀÇ Å©±â(¹ÙÀÌÆ® ´ÜÀ§).
*
*               err      ¿¡·¯ Äڵ带 ÀúÀåÇÒ ¸Þ¸ð¸®¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*                        ´ÙÀ½°ú °°Àº °ªÀ» °®´Â´Ù.
*             
*                        OS_NO_ERR            ¸Þ¸ð¸® ÆÄƼ¼ÇÀ» Á¤»óÀûÀ¸·Î »ý¼ºÇßÀ½.
*                        OS_MEM_INVALID_PART  ÀÚÀ¯ ÆÄƼ¼ÇÀ» »ý¼ºÇÒ ¼ö ¾øÀ½.
*                        OS_MEM_INVALID_BLKS  ºí·Ï ¼ö¸¦ Àß ¸ø ÁöÁ¤ÇßÀ½(2¿Í °°°Å³ª Ä¿¾ßÇÔ).
*                        OS_MEM_INVALID_SIZE  ºí·Ï Å©±â¸¦ À߸ø ÁöÁ¤ÇßÀ½.
*                                             (Æ÷ÀÎÅÍ Å©±âº¸´Ù Ä¿¾ßÇÔ)
* ¸®Åϰª      : != (OS_MEM *)0  »ý¼ºÇÑ ÆÄƼ¼ÇÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*               == (OS_MEM *)0  Àü´ÞÀÎÀÚ¸¦ Àß ¸ø ÁöÁ¤Çؼ­ ÆÄƼ¼ÇÀ» »ý¼ºÇÏÁö ¸øÇÑ °æ¿ì.
*                               ÀÚÀ¯ ÆÄƼ¼ÇÀÌ ¾øÀ½.
*********************************************************************************************************
*/

OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
    OS_MEM  *pmem;
    INT8U   *pblk;
    void   **plink;
    INT32U   i;


    if (nblks < 2) {                                  /* ÆÄƼ¼Ç´ç ÃÖ¼ÒÇÑ 2ºí·ÏÀ» Æ÷ÇÔÇØ¾ß ÇÔ           */
        *err = OS_MEM_INVALID_BLKS;
        return ((OS_MEM *)0);
    }
    if (blksize < sizeof(void *)) {                   /* ÃÖ¼ÒÇÑ Æ÷ÀÎÅ͸¦ ÀúÀåÇÒ ¼ö ÀÖ´Â ºí·ÏÅ©±â ÇÊ¿ä  */
        *err = OS_MEM_INVALID_SIZE;
        return ((OS_MEM *)0);
    }
    OS_ENTER_CRITICAL();
    pmem = OSMemFreeList;                             /* ÀÚÀ¯ ¸Þ¸ð¸® ÆÄƼ¼ÇÀ» ¾òÀ½                     */
    if (OSMemFreeList != (OS_MEM *)0) {               /* ÀÚÀ¯ ÆÄƼ¼Ç Ç®ÀÌ ºñ¾ú´ÂÁö È®ÀÎ                */
        OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
    }
    OS_EXIT_CRITICAL();
    if (pmem == (OS_MEM *)0) {                        /* ¸Þ¸ð¸® ÆÄƼ¼ÇÀ» ¾ò¾ú´ÂÁö È®ÀÎ                 */
        *err = OS_MEM_INVALID_PART;
        return ((OS_MEM *)0);
    }
    plink = (void **)addr;                            /* ÀÚÀ¯ ¸Þ¸ð¸® ºí·ÏÀÇ ¸µÅ©µå ¸®½ºÆ® »ý¼º         */
    pblk  = (INT8U *)addr + blksize;
    for (i = 0; i < (nblks - 1); i++) {
        *plink = (void *)pblk;
        plink  = (void **)pblk;
        pblk   = pblk + blksize;
    }
    *plink = (void *)0;                               /* ¸¶Áö¸· ºí·ÏÀº NULLÀ» °¡¸®Å²´Ù                 */
    OS_ENTER_CRITICAL();
    pmem->OSMemAddr     = addr;                       /* ¸Þ¸ð¸® ÆÄƼ¼ÇÀÇ ½ÃÀÛ ÁÖ¼Ò ÀúÀå                */
    pmem->OSMemFreeList = addr;                       /* Æ÷ÀÎÅ͸¦ ÀÚÀ¯ ºí·Ï pool·Î °¡¸®Å²´Ù            */
    pmem->OSMemNFree    = nblks;                      /* ÀÚÀ¯ ºí·Ï ¼ö¸¦ MCB¿¡ ÀúÀå                     */
    pmem->OSMemNBlks    = nblks;
    pmem->OSMemBlkSize  = blksize;                    /* °¢ ºí·ÏÀÇ Å©±â ÀúÀå                           */
    OS_EXIT_CRITICAL();
    *err   = OS_NO_ERR;
    return (pmem);
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                          ¸Þ¸ð¸® ºí·Ï ÇÒ´ç
*
* ¼³¸í        : ÆÄƼ¼Ç¿¡¼­ ¸Þ¸ð¸® ºí·ÏÀ» ¾ò´Â´Ù.
*
* Àü´ÞÀÎÀÚ    : pmem    ¸Þ¸ð¸® ÆÄƼ¼Ç ÄÁÆ®·Ñ ºí·ÏÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*
*               err     ¿¡·¯ Äڵ带 ÀúÀåÇÒ ¸Þ¸ð¸®¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*                       ´ÙÀ½°ú °°Àº °ªÀ» °®´Â´Ù.
*
*                       OS_NO_ERR           ¸Þ¸ð¸® ÆÄƼ¼ÇÀ» Á¤»óÀûÀ¸·Î »ý¼ºÇßÀ½.
*                       OS_MEM_NO_FREE_BLKS È£ÃâÀÚ¿¡°Ô ÇÒ´çÇØÁÙ ÀÚÀ¯ ¸Þ¸ð¸® ºí·ÏÀÌ ¾øÀ½.
*
* ¸®Åϰª      : ¿¡·¯°¡ ¾øÀ» °æ¿ì ÇÒ´çµÈ ºí·ÏÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*               ¿¡·¯°¡ ¹ß»ýÇÑ °æ¿ì´Â NULLÀ» µ¹·ÁÁØ´Ù.
*********************************************************************************************************
*/

void *OSMemGet (OS_MEM *pmem, INT8U *err)
{
    void    *pblk;


    OS_ENTER_CRITICAL();
    if (pmem->OSMemNFree > 0) {                       /* ÀÚÀ¯ ¸Þ¸ð¸® ºí·ÏÀÌ ÀÖ´ÂÁö È®ÀÎ                */
        pblk                = pmem->OSMemFreeList;    /* ¿¹, ´ÙÀ½ ÀÚÀ¯ ¸Þ¸ð¸® ºí·ÏÀ» °¡¸®Å²´Ù          */
        pmem->OSMemFreeList = *(void **)pblk;         /*      »õ ÀÚÀ¯ ¸®½ºÆ®¸¦ °¡¸®Å°µµ·Ï Æ÷ÀÎÅÍ Á¶Á¤  */
        pmem->OSMemNFree--;                           /*      ÀÌ ÆÄƼ¼Ç¿¡¼­ÀÇ °¡¿ë ¸Þ¸ð¸® ºí·Ï ¼ö °¨¼Ò */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;                             /*      ¿¡·¯ ¾øÀ½                                */
        return (pblk);                                /*      È£ÃâÀÚ·Î ¸Þ¸ð¸® ºí·ÏÀ» ¸®ÅÏ              */
    } else {
        OS_EXIT_CRITICAL();
        *err = OS_MEM_NO_FREE_BLKS;                   /* ¾Æ´Ï¿À, È£ÃâÀÚ¿¡°Ô ¸Þ¸ð¸® ºí·ÏÀÌ ¾øÀ½À» ¾Ë¸²  */
        return ((void *)0);                           /*      NULL Æ÷ÀÎÅ͸¦ ¸®ÅÏ                       */
    }
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                        ¸Þ¸ð¸® ÆÄƼ¼Ç °ü¸®ÀÚ ÃʱâÈ­
*
* ¼³¸í        : ¸Þ¸ð¸® °ü¸®ÀÚ¸¦ ÃʱâÈ­Çϱâ À§ÇØ uC/OS-II°¡ È£ÃâÇÏ´Â ÇÔ¼ö.
*               ÀÀ¿ëÇÁ·Î±×·¥Àº ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÏ¸é ¾ÈµÈ´Ù.
*
* Àü´ÞÀÎÀÚ    : ¾øÀ½
*
* ¸®Åϰª      : ¾øÀ½
*********************************************************************************************************
*/

void OSMemInit (void)
{
    OS_MEM  *pmem;
    INT16U   i;


    pmem = (OS_MEM *)&OSMemTbl[0];                    /* ¸Þ¸ð¸® ÄÁÆ®·Ñ ºí·Ï(MCB)À» °¡¸®Å²´Ù            */
    for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {     /* ÀÚÀ¯ ¸Þ¸ð¸® ÆÄƼ¼Ç ¸®½ºÆ® ÃʱâÈ­              */
        pmem->OSMemFreeList = (void *)&OSMemTbl[i+1]; /* ÀÚÀ¯ ÆÄƼ¼Ç ¿¬°á ¸®Æ®½º                       */
        pmem->OSMemAddr     = (void *)0;              /* ¸Þ¸ð¸® ÆÄƼ¼ÇÀÇ ½ÃÀÛ ÁÖ¼Ò ÀúÀå                */
        pmem->OSMemNFree    = 0;                      /* ÀÚÀ¯ ºí·ÏÀÌ ¾øÀ½                              */
        pmem->OSMemNBlks    = 0;                      /* ºí·Ï ¾øÀ½                                     */
        pmem->OSMemBlkSize  = 0;                      /* Å©±â 0                                        */
        pmem++;
    }
    OSMemTbl[OS_MAX_MEM_PART - 1].OSMemFreeList = (void *)0;
    OSMemFreeList                               = (OS_MEM *)&OSMemTbl[0];
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                           ¸Þ¸ð¸® ºí·Ï ÇØÁ¦
*
* ¼³¸í        : ¸Þ¸ð¸® ºí·ÏÀ» ÆÄƼ¼ÇÀ¸·Î µ¹·ÁÁØ´Ù.
*
* Àü´ÞÀÎÀÚ    : pmem    ¸Þ¸ð¸® ÆÄƼ¼Ç ÄÁÆ®·Ñ ºí·ÏÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*
*               pblk    ÇØÁ¦ÇÏ·Á´Â ¸Þ¸ð¸® ºí·ÏÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*
* ¸®Åϰª      : OS_NO_ERR         ¸Þ¸ð¸® ºí·ÏÀ» ¼º°øÀûÀ¸·Î ¸Þ¸ð¸® ÆÄƼ¼Ç¿¡ µ¹·ÁÁáÀ½.
*               OS_MEM_FULL       ÀÌ¹Ì Âù ¸Þ¸ð¸® ÆÄƼ¼Ç¿¡ ºí·ÏÀ» µ¹·ÁÁÖ·Á°í ½ÃµµÇßÀ½.
*                                 (ÇÒ´çÇÑ ºí·Ï ÀÌ»óÀÇ ºí·ÏÀ» ÇØÁ¦ÇÏ·Á ÇßÀ½!)
*********************************************************************************************************
*/

INT8U OSMemPut (OS_MEM  *pmem, void *pblk)
{
    OS_ENTER_CRITICAL();
    if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* ¸ðµç ºí·ÏÀ» ÀÌ¹Ì ÇØÁ¦Çß´ÂÁö È®ÀÎ                   */
        OS_EXIT_CRITICAL();
        return (OS_MEM_FULL);       
    }
    *(void **)pblk      = pmem->OSMemFreeList;   /* ÇØÁ¦ÇÏ·Á´Â ºí·ÏÀ» ÀÚÀ¯ ºí·Ï ¸®½ºÆ®¿¡ »ðÀÔ          */
    pmem->OSMemFreeList = pblk;
    pmem->OSMemNFree++;                          /* ÆÄƼ¼Ç¿¡ ÀÖ´Â ºí·Ï ¼ö¸¦ Áõ°¡                       */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);                          /* ºí·ÏÀ» ÇØÁ¦ÇßÀ½À» È£ÃâÀÚ¿¡°Ô ¾Ë¸²                  */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                        ¸Þ¸ð¸® ÆÄƼ¼Ç »óÅ ¾ò±â
*
* ¼³¸í        : ÀÌ ÇÔ¼ö´Â ¸Þ¸ð¸® ÆÄƼ¼Ç¿¡¼­ »ç¿ëÇÑ ¸Þ¸ð¸® ºí·Ï ¼ö¿Í ÀÚÀ¯ ¸Þ¸ð¸® ºí·Ï ¼ö¸¦ ¾Ë¾Æ³½´Ù.
*
*
* Àü´ÞÀÎÀÚ    : pmem    ¸Þ¸ð¸® ÆÄƼ¼Ç ÄÁÆ®·Ñ ºí·ÏÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*
*               pdata   ¸Þ¸ð¸® ÆÄƼ¼Ç¿¡ ´ëÇÑ Á¤º¸¸¦ ÀúÀåÇÒ ±¸Á¶Ã¼¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ.
*
*
* ¸®Åϰª      : OS_NO_ERR         Ç×»ó ¿¡·¯°¡ ¾øÀ½.
*********************************************************************************************************
*/

INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *pdata)
{
    OS_ENTER_CRITICAL();
    pdata->OSAddr     = pmem->OSMemAddr;
    pdata->OSFreeList = pmem->OSMemFreeList;
    pdata->OSBlkSize  = pmem->OSMemBlkSize;
    pdata->OSNBlks    = pmem->OSMemNBlks;
    pdata->OSNFree    = pmem->OSMemNFree;
    OS_EXIT_CRITICAL();
    pdata->OSNUsed    = pdata->OSNBlks - pdata->OSNFree;
    return (OS_NO_ERR);                         
}
#endif