PageRenderTime 150ms CodeModel.GetById 131ms app.highlight 12ms RepoModel.GetById 2ms app.codeStats 0ms

/src/compiler/ucos-vs2008/UCOS_SIM/src/ucosii/os_mem.c

http://ftk.googlecode.com/
C | 416 lines | 236 code | 33 blank | 147 comment | 47 complexity | 4ede0aceb00ba5b25452cacc4c96986d MD5 | raw file
  1/*
  2*********************************************************************************************************
  3*                                                uC/OS-II
  4*                                          The Real-Time Kernel
  5*                                            MEMORY MANAGEMENT
  6*
  7*                          (c) Copyright 1992-2005, Jean J. Labrosse, Weston, FL
  8*                                           All Rights Reserved
  9*
 10* File    : OS_MEM.C
 11* By      : Jean J. Labrosse
 12* Version : V2.80
 13*********************************************************************************************************
 14*/
 15
 16#ifndef  OS_MASTER_FILE
 17#include <ucos_ii.h>
 18#endif
 19
 20#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
 21/*
 22*********************************************************************************************************
 23*                                        CREATE A MEMORY PARTITION
 24*
 25* Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.
 26*
 27* Arguments   : addr     is the starting address of the memory partition
 28*
 29*               nblks    is the number of memory blocks to create from the partition.
 30*
 31*               blksize  is the size (in bytes) of each block in the memory partition.
 32*
 33*               err      is a pointer to a variable containing an error message which will be set by
 34*                        this function to either:
 35*
 36*                        OS_NO_ERR            if the memory partition has been created correctly.
 37*                        OS_MEM_INVALID_ADDR  you are specifying an invalid address for the memory
 38*                                             storage of the partition.
 39*                        OS_MEM_INVALID_PART  no free partitions available
 40*                        OS_MEM_INVALID_BLKS  user specified an invalid number of blocks (must be >= 2)
 41*                        OS_MEM_INVALID_SIZE  user specified an invalid block size
 42*                                             (must be greater than the size of a pointer)
 43* Returns    : != (OS_MEM *)0  is the partition was created
 44*              == (OS_MEM *)0  if the partition was not created because of invalid arguments or, no
 45*                              free partition is available.
 46*********************************************************************************************************
 47*/
 48
 49OS_MEM  *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
 50{
 51    OS_MEM    *pmem;
 52    INT8U     *pblk;
 53    void     **plink;
 54    INT32U     i;
 55#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
 56    OS_CPU_SR  cpu_sr = 0;
 57#endif
 58
 59
 60
 61#if OS_ARG_CHK_EN > 0
 62    if (err == (INT8U *)0) {                          /* Validate 'err'                                */
 63        return ((OS_MEM *)0);
 64    }
 65    if (addr == (void *)0) {                          /* Must pass a valid address for the memory part.*/
 66        *err = OS_MEM_INVALID_ADDR;
 67        return ((OS_MEM *)0);
 68    }
 69    if (nblks < 2) {                                  /* Must have at least 2 blocks per partition     */
 70        *err = OS_MEM_INVALID_BLKS;
 71        return ((OS_MEM *)0);
 72    }
 73    if (blksize < sizeof(void *)) {                   /* Must contain space for at least a pointer     */
 74        *err = OS_MEM_INVALID_SIZE;
 75        return ((OS_MEM *)0);
 76    }
 77#endif
 78    OS_ENTER_CRITICAL();
 79    pmem = OSMemFreeList;                             /* Get next free memory partition                */
 80    if (OSMemFreeList != (OS_MEM *)0) {               /* See if pool of free partitions was empty      */
 81        OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
 82    }
 83    OS_EXIT_CRITICAL();
 84    if (pmem == (OS_MEM *)0) {                        /* See if we have a memory partition             */
 85        *err = OS_MEM_INVALID_PART;
 86        return ((OS_MEM *)0);
 87    }
 88    plink = (void **)addr;                            /* Create linked list of free memory blocks      */
 89    pblk  = (INT8U *)((INT32U)addr + blksize);
 90    for (i = 0; i < (nblks - 1); i++) {
 91       *plink = (void *)pblk;                         /* Save pointer to NEXT block in CURRENT block   */
 92        plink = (void **)pblk;                        /* Position to  NEXT      block                  */
 93        pblk  = (INT8U *)((INT32U)pblk + blksize);    /* Point to the FOLLOWING block                  */
 94    }
 95    *plink              = (void *)0;                  /* Last memory block points to NULL              */
 96    pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
 97    pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
 98    pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
 99    pmem->OSMemNBlks    = nblks;
100    pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
101    *err                = OS_NO_ERR;
102    return (pmem);
103}
104/*$PAGE*/
105/*
106*********************************************************************************************************
107*                                          GET A MEMORY BLOCK
108*
109* Description : Get a memory block from a partition
110*
111* Arguments   : pmem    is a pointer to the memory partition control block
112*
113*               err     is a pointer to a variable containing an error message which will be set by this
114*                       function to either:
115*
116*                       OS_NO_ERR           if the memory partition has been created correctly.
117*                       OS_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
118*                       OS_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
119*
120* Returns     : A pointer to a memory block if no error is detected
121*               A pointer to NULL if an error is detected
122*********************************************************************************************************
123*/
124
125void  *OSMemGet (OS_MEM *pmem, INT8U *err)
126{
127    void      *pblk;
128#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
129    OS_CPU_SR  cpu_sr = 0;
130#endif
131
132
133
134#if OS_ARG_CHK_EN > 0
135    if (err == (INT8U *)0) {                          /* Validate 'err'                                */
136        return ((void *)0);
137    }
138    if (pmem == (OS_MEM *)0) {                        /* Must point to a valid memory partition        */
139        *err = OS_MEM_INVALID_PMEM;
140        return ((void *)0);
141    }
142#endif
143    OS_ENTER_CRITICAL();
144    if (pmem->OSMemNFree > 0) {                       /* See if there are any free memory blocks       */
145        pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
146        pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
147        pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
148        OS_EXIT_CRITICAL();
149        *err = OS_NO_ERR;                             /*      No error                                 */
150        return (pblk);                                /*      Return memory block to caller            */
151    }
152    OS_EXIT_CRITICAL();
153    *err = OS_MEM_NO_FREE_BLKS;                       /* No,  Notify caller of empty memory partition  */
154    return ((void *)0);                               /*      Return NULL pointer to caller            */
155}
156/*$PAGE*/
157/*
158*********************************************************************************************************
159*                                   GET THE NAME OF A MEMORY PARTITION
160*
161* Description: This function is used to obtain the name assigned to a memory partition.
162*
163* Arguments  : pmem      is a pointer to the memory partition
164*
165*              pname     is a pointer to an ASCII string that will receive the name of the memory partition.
166*
167*              err       is a pointer to an error code that can contain one of the following values:
168*
169*                        OS_NO_ERR                  if the name was copied to 'pname'
170*                        OS_MEM_INVALID_PMEM        if you passed a NULL pointer for 'pmem'
171*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
172*
173* Returns    : The length of the string or 0 if 'pmem' is a NULL pointer.
174*********************************************************************************************************
175*/
176
177#if OS_MEM_NAME_SIZE > 1
178INT8U  OSMemNameGet (OS_MEM *pmem, INT8U *pname, INT8U *err)
179{
180    INT8U      len;
181#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
182    OS_CPU_SR  cpu_sr = 0;
183#endif
184
185
186
187    OS_ENTER_CRITICAL();
188#if OS_ARG_CHK_EN > 0
189    if (err == (INT8U *)0) {                     /* Validate 'err'                                     */
190        OS_EXIT_CRITICAL();
191        return (0);
192    }
193    if (pmem == (OS_MEM *)0) {                   /* Is 'pmem' a NULL pointer?                          */
194        OS_EXIT_CRITICAL();                      /* Yes                                                */
195        *err = OS_MEM_INVALID_PMEM;
196        return (0);
197    }
198    if (pname == (INT8U *)0) {                    /* Is 'pname' a NULL pointer?                         */
199        OS_EXIT_CRITICAL();                      /* Yes                                                */
200        *err = OS_ERR_PNAME_NULL;
201        return (0);
202    }
203#endif
204    len  = OS_StrCopy(pname, pmem->OSMemName);   /* Copy name from OS_MEM                              */
205    OS_EXIT_CRITICAL();
206    *err = OS_NO_ERR;
207    return (len);
208}
209#endif
210
211/*$PAGE*/
212/*
213*********************************************************************************************************
214*                                 ASSIGN A NAME TO A MEMORY PARTITION
215*
216* Description: This function assigns a name to a memory partition.
217*
218* Arguments  : pmem      is a pointer to the memory partition
219*
220*              pname     is a pointer to an ASCII string that contains the name of the memory partition.
221*
222*              err       is a pointer to an error code that can contain one of the following values:
223*
224*                        OS_NO_ERR                  if the name was copied to 'pname'
225*                        OS_MEM_INVALID_PMEM        if you passed a NULL pointer for 'pmem'
226*                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
227*						 OS_MEM_NAME_TOO_LONG       if the name doesn't fit in the storage area
228*
229* Returns    : None
230*********************************************************************************************************
231*/
232
233#if OS_MEM_NAME_SIZE > 1
234void  OSMemNameSet (OS_MEM *pmem, INT8U *pname, INT8U *err)
235{
236    INT8U      len;
237#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
238    OS_CPU_SR  cpu_sr = 0;
239#endif
240
241
242
243    OS_ENTER_CRITICAL();
244#if OS_ARG_CHK_EN > 0
245    if (err == (INT8U *)0) {                     /* Validate 'err'                                     */
246        OS_EXIT_CRITICAL();
247        return;
248    }
249    if (pmem == (OS_MEM *)0) {                   /* Is 'pmem' a NULL pointer?                          */
250        OS_EXIT_CRITICAL();                      /* Yes                                                */
251        *err = OS_MEM_INVALID_PMEM;
252        return;
253    }
254    if (pname == (INT8U *)0) {                    /* Is 'pname' a NULL pointer?                         */
255        OS_EXIT_CRITICAL();                      /* Yes                                                */
256        *err = OS_ERR_PNAME_NULL;
257        return;
258    }
259#endif
260    len = OS_StrLen(pname);                      /* Can we fit the string in the storage area?         */
261    if (len > (OS_MEM_NAME_SIZE - 1)) {          /* No                                                 */
262        OS_EXIT_CRITICAL();
263        *err = OS_MEM_NAME_TOO_LONG;
264        return;
265    }
266    (void)OS_StrCopy(pmem->OSMemName, pname);    /* Yes, copy name to the memory partition header      */
267    OS_EXIT_CRITICAL();
268    *err = OS_NO_ERR;
269}
270#endif
271
272/*$PAGE*/
273/*
274*********************************************************************************************************
275*                                         RELEASE A MEMORY BLOCK
276*
277* Description : Returns a memory block to a partition
278*
279* Arguments   : pmem    is a pointer to the memory partition control block
280*
281*               pblk    is a pointer to the memory block being released.
282*
283* Returns     : OS_NO_ERR            if the memory block was inserted into the partition
284*               OS_MEM_FULL          if you are returning a memory block to an already FULL memory
285*                                    partition (You freed more blocks than you allocated!)
286*               OS_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
287*               OS_MEM_INVALID_PBLK  if you passed a NULL pointer for the block to release.
288*********************************************************************************************************
289*/
290
291INT8U  OSMemPut (OS_MEM *pmem, void *pblk)
292{
293#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
294    OS_CPU_SR  cpu_sr = 0;
295#endif
296
297
298
299#if OS_ARG_CHK_EN > 0
300    if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
301        return (OS_MEM_INVALID_PMEM);
302    }
303    if (pblk == (void *)0) {                     /* Must release a valid block                         */
304        return (OS_MEM_INVALID_PBLK);
305    }
306#endif
307    OS_ENTER_CRITICAL();
308    if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
309        OS_EXIT_CRITICAL();
310        return (OS_MEM_FULL);
311    }
312    *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
313    pmem->OSMemFreeList = pblk;
314    pmem->OSMemNFree++;                          /* One more memory block in this partition            */
315    OS_EXIT_CRITICAL();
316    return (OS_NO_ERR);                          /* Notify caller that memory block was released       */
317}
318/*$PAGE*/
319/*
320*********************************************************************************************************
321*                                          QUERY MEMORY PARTITION
322*
323* Description : This function is used to determine the number of free memory blocks and the number of
324*               used memory blocks from a memory partition.
325*
326* Arguments   : pmem        is a pointer to the memory partition control block
327*
328*               p_mem_data  is a pointer to a structure that will contain information about the memory
329*                           partition.
330*
331* Returns     : OS_NO_ERR            If no errors were found.
332*               OS_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
333*               OS_MEM_INVALID_PDATA if you passed a NULL pointer to the data recipient.
334*********************************************************************************************************
335*/
336
337#if OS_MEM_QUERY_EN > 0
338INT8U  OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *p_mem_data)
339{
340#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
341    OS_CPU_SR  cpu_sr = 0;
342#endif
343
344
345
346#if OS_ARG_CHK_EN > 0
347    if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
348        return (OS_MEM_INVALID_PMEM);
349    }
350    if (p_mem_data == (OS_MEM_DATA *)0) {        /* Must release a valid storage area for the data     */
351        return (OS_MEM_INVALID_PDATA);
352    }
353#endif
354    OS_ENTER_CRITICAL();
355    p_mem_data->OSAddr     = pmem->OSMemAddr;
356    p_mem_data->OSFreeList = pmem->OSMemFreeList;
357    p_mem_data->OSBlkSize  = pmem->OSMemBlkSize;
358    p_mem_data->OSNBlks    = pmem->OSMemNBlks;
359    p_mem_data->OSNFree    = pmem->OSMemNFree;
360    OS_EXIT_CRITICAL();
361    p_mem_data->OSNUsed    = p_mem_data->OSNBlks - p_mem_data->OSNFree;
362    return (OS_NO_ERR);
363}
364#endif                                           /* OS_MEM_QUERY_EN                                    */
365/*$PAGE*/
366/*
367*********************************************************************************************************
368*                                    INITIALIZE MEMORY PARTITION MANAGER
369*
370* Description : This function is called by uC/OS-II to initialize the memory partition manager.  Your
371*               application MUST NOT call this function.
372*
373* Arguments   : none
374*
375* Returns     : none
376*
377* Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
378*********************************************************************************************************
379*/
380
381void  OS_MemInit (void)
382{
383#if OS_MAX_MEM_PART == 1
384    OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));   /* Clear the memory partition table          */
385    OSMemFreeList               = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list           */
386#if OS_MEM_NAME_SIZE > 1
387    OSMemFreeList->OSMemName[0] = '?';                    /* Unknown name                              */
388    OSMemFreeList->OSMemName[1] = OS_ASCII_NUL;
389#endif
390#endif
391
392#if OS_MAX_MEM_PART >= 2
393    OS_MEM  *pmem;
394    INT16U   i;
395
396
397    OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));   /* Clear the memory partition table          */
398    pmem = &OSMemTbl[0];                                  /* Point to memory control block (MCB)       */
399    for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {         /* Init. list of free memory partitions      */
400        pmem->OSMemFreeList = (void *)&OSMemTbl[i+1];     /* Chain list of free partitions             */
401#if OS_MEM_NAME_SIZE > 1
402        pmem->OSMemName[0]  = '?';                        /* Unknown name                              */
403        pmem->OSMemName[1]  = OS_ASCII_NUL;
404#endif
405        pmem++;
406    }
407    pmem->OSMemFreeList = (void *)0;                      /* Initialize last node                      */
408#if OS_MEM_NAME_SIZE > 1
409    pmem->OSMemName[0]  = '?';                            /* Unknown name                              */
410    pmem->OSMemName[1]  = OS_ASCII_NUL;
411#endif
412
413    OSMemFreeList       = &OSMemTbl[0];                   /* Point to beginning of free list           */
414#endif
415}
416#endif                                                    /* OS_MEM_EN                                 */