lib.h

来自「Nucleus实时操作系统是Accelerater Technology公司开发」· C头文件 代码 · 共 225 行

H
225
字号
/********************************************************
	Copyright 1985 Software Development Systems, Inc.

	Copy of s2 to the end of s1.
	Return a pointer to the null-terminated result.
********************************************************/
#include "string.h"
#include <stdlib.h>
#include <errno.h>
#include "abbr.h"
#include "alloc.h"

extern void *_brkp;
extern long _brksz;


char *strcpy(s1, s2)
register char *s1;
register const char *s2;
{
    register char *p = s1;

    while( *s1++ = *s2++ ) ;

    return p;
}

size_t strlen(s1)
register const char *s1;
{
    register const char *s2 = s1;

    while ( *s1++ );

    return s1 - s2 - 1;
}


/****************************************************************
	Memory allocator.
	Copyright 1992 Software Development Systems, Inc.
	All Rights Reserved.
****************************************************************/

/************************************************************************
    NOTE: These pointers are assumed to be ZEROed on startup.
    This happens automatically because the startup code zeroes the
    region "ram" before it calls "main".  However, if you modify
    the startup code or change the region these variables go into,
    make sure you still zero these variables before using any
    of the "malloc" routines.
************************************************************************/
struct hdr *_first_area;	/* Head of doubly linked area list */
struct hdr *_last_area;		/* Dummy area at end of last section */
struct hdr *_free_list;		/* Head of doubly linked free list */

/************************************************************************
    Insert area pointed to by "p" into the doubly linked free list.
    (Assumes that DISABLE was already called.)
************************************************************************/
void _infree( struct hdr *p ) {
    p->bckfree = 0;
    if ( p->fwdfree = _free_list ) _free_list->bckfree = p;
    _free_list = p; }

/************************************************************************
    Remove area pointed to by "p" from the doubly linked free list.
    (Assumes that DISABLE was already called.)
************************************************************************/
void _rmfree( struct hdr *p ) {  register struct hdr *f, *b;
    f = p->fwdfree;
    b = p->bckfree;
    if ( b ) b->fwdfree = f;
    else     _free_list = f;
    if ( f ) f->bckfree = b; }

/***********************************************************************
    Allocate a new area of at least "sizeneeded" bytes.
    Return zero on failure, setting errno to ENOMEM.
    Also return zero if "sizeneeded" is zero.
***********************************************************************/
void *malloc( register size_t sizeneeded ) {
    register struct hdr *p, *x, *bestbig;
    register size_t sizebig, size;  auto long realsz;

    if ( !sizeneeded ) return 0;

    sizeneeded = ((sizeneeded + ALIGNMASK) & ~ALIGNMASK) + sizeof(struct busy);
    if ( sizeneeded < sizeof(struct hdr) ) sizeneeded = sizeof(struct hdr);

    /****************************************************************
	Look down the free list to find an area which contains
	enough bytes.  The first one found that is large enough
	but not twice as large will be used.  We keep track of
	the smallest one that is twice as large or larger so we
	can use it if we don't find anything smaller in the list.
    ****************************************************************/
    bestbig = 0;	/* best big one so far (size will be in sizebig) */
    sizebig = 0;	/* no size yet (avoids warning message) */
    DISABLE();
    for ( p = _free_list; p; p = p->fwdfree ) {
	if ( (size = (char*)p->busy.nextarea - (char*)p) >= sizeneeded ) {
	    if ( size < sizeneeded+sizeneeded ) break;
	    if ( !bestbig || size<sizebig ) { bestbig = p; sizebig = size; }}}

    if ( !p && !(p = bestbig) ) {
	/****************************************************************
	    No available area is big enough.  Get a new section of
	    memory from the system with enough extra bytes for a dummy
	    area header at the end of the section.  Turn the section
	    into a free area and a dummy busy area.  (The actual amount
	    of memory allocated in the section by "mbrk" will often be
	    more than requested, at the discretion of "mbrk".)
	****************************************************************/
	if ( !(p=(struct hdr*)mbrk(
		    (long)(sizeneeded+sizeof(struct busy)), &realsz )) ) {
	    errno = ENOMEM;
	    ENABLE();
	    return 0; }

	realsz &= ~ALIGNMASK;

	if ( _last_area &&
	     (char*)p == ((char*)_last_area + sizeof(struct busy)) ) {
	    /********************************************************
		New section is contiguous with the last section
		returned by "mbrk" so use the old "_last_area" header
		as the header for the new free area.
		(Note: section sizes returned by "mbrk" must be a
		multiple of the size of a pointer for the contiguous
		test to succeed.)
	    ********************************************************/
	    p = _last_area;
	    realsz += sizeof(struct busy);
	    /********************************************************
		Check if previous area is free and combine it now.
	    ********************************************************/
	    if ( (x = p->busy.prevarea) && !ISBUSY(x) ) {
		_rmfree( x );		/* remove area x from free list */
		realsz += (char*)p - (char*)x;
		p = x; }}		/* prepare to rewrite header of x */
	else {
	    /********************************************************
		Create a new header for the new free area.
	    ********************************************************/
	    if ( _last_area ) {
		p->busy.prevarea = _last_area;
		_last_area->busy.nextarea = (struct hdr*)((char*)p+BUSY); }
	    else {
		p->busy.prevarea = 0;
		_first_area = p; }}

	/********************************************************
	    Reserve a minimal dummy area (just a busy header)
	    at the end of the new memory section to represent
	    any gap that may occur between this section and the
	    next section.  The "nextarea" pointer of the new
	    free area points to this busy dummy area.
	********************************************************/
	p->busy.nextarea = _last_area =
	    (struct hdr *)((char*)p + realsz - sizeof(struct busy));
	_last_area->busy.prevarea = p;
	_last_area->busy.nextarea = (struct hdr *)BUSY;

	/****************************************************************
	    Insert the new free area into the doubly linked free list.
	****************************************************************/
	_infree(p); }

    /****************************************************************
	The free area to use is pointed to by "p".
    ****************************************************************/
    if ( (char*)p->busy.nextarea-(char*)p-sizeneeded > sizeof(struct hdr) ) {
	/***************************************************************
	    Remove free area "p" from the free list, split it into
	    two areas, putting the second area in the free list
	    and turning first area into a busy area and returning
	    its data pointer.
	    (NOTE: although this is slightly more work than leaving
	    the first area in the free list and making the second
	    area be busy, it is better to keep the free area at the
	    end of the section so that it might be combined with
	    area in a newly allocated contiguous section later.)
	***************************************************************/
	x = (struct hdr*)((char*)p + sizeneeded);
	p->busy.nextarea->busy.prevarea = x;
	x->busy.prevarea = p;
	x->busy.nextarea = p->busy.nextarea;
	p->busy.nextarea = (struct hdr*)((char*)x + BUSY);
	_rmfree( p );
	_infree( x ); }
    else {
	/*****************************************************************
	    Remove free area "p" from the doubly linked free list,
	    and turn free area "p" into a busy area.
	*****************************************************************/
	_rmfree( p );
	p->busy.nextarea = (struct hdr*)((char*)p->busy.nextarea+BUSY); }

    /****************************************************************
	Return data pointer for area "p".
    ****************************************************************/
    ENABLE();
    return (char*)p + sizeof(struct busy); }

/****************************************************************
	Copyright 1988 Software Development Systems, Inc.

	This is the default mbrk() function, used with malloc()
	and calloc().  This mbrk() will succeed the first time
	it gets a request for a memory section with no more than
	_brksz bytes, and in that case returns the section
	indicated by _brkp,_brksz.  All other times this
	function returns 0.  The code in "start.s" initializes
	_brkp,_brksz to the address and size of the region
	"malloc" declared in the link specification file "spec".
****************************************************************/


char *mbrk( long size, long *realsize ) {
    if ( size > _brksz ) return 0;
    *realsize = _brksz;
    _brksz = 0;
    return _brkp; }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?