mt_realloc.c 3.29 KB
/*
=============================================================================
        Copyright (C) 1997-1999 NINTENDO Co.,Ltd.
        
        $RCSfile: mt_realloc.c,v $
        $Revision: 1.1.1.1 $
        $Date: 2002/10/30 02:07:09 $
=============================================================================
関数名:mt_realloc
-----------------------------------------------------------------------------
書式:  #include <malloc.h>
        void *mt_realloc(void *ptr, int size);
説明: マルチスレッド対応の realloc()。
       引数や戻り値、その他の説明については、realloc() と同じなので、
       そちらの説明を参照すること。
-----------------------------------------------------------------------------
*/
#include    <ultra64.h>
#include    "string.h"
#include    "malloc.h"
#include    "_malloc.h"

void *mt_realloc(void *ptr, int size)
{
    unsigned int    *next2;
    unsigned int    size2;
    unsigned char   *p2;
    struct  mallocST  *malloc_st_ptr ;
    OSIntMask svintmask ;
    void *ret ;

    if( (int)malloc_ptr == -1 ){
	return  NULL;
    }

    svintmask = osSetIntMask( OS_IM_NONE ) ; /* 全ての割り込みを不許可 */

    if( !ptr ){
	ret = _malloc( malloc_ptr, size ); /*  新規にメモリ確保 */
	osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
	return ret ;
    }

    if( !size ){ /* 現在のメモリを開放 */
        _free(malloc_ptr, ptr);
	osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
        return  NULL;
    }

    size += 15;
    size &= (~15);

    p2 = (unsigned char *)ptr - MALLOC_HEADSIZE;
    malloc_st_ptr = (struct mallocST *)p2;

    if( !malloc_st_ptr->flag ){
	osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
	return NULL;
    }

    next2 = malloc_st_ptr->next;
    size2 = malloc_st_ptr->size;

    malloc_st_ptr = (struct mallocST *)next2;
    if (next2 && !malloc_st_ptr->flag)  {
        size2 += malloc_st_ptr->size + MALLOC_HEADSIZE;
        next2 = (unsigned int *)malloc_st_ptr->next;
    }

    malloc_st_ptr = (struct mallocST *)p2;
    if( size > size2 ){
        /*  現在のポインタの位置からでは指定サイズ確保が出来ない。 */
        p2 = (unsigned char *)_malloc(malloc_ptr, size);
        if( p2 == NULL ){
	    osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
	    return  NULL;
	}
        _nmemcpy(p2, ptr, size);
        _free(malloc_ptr, ptr);
	osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
        return  p2;
    }else{
        /*  今のポインタを継承したままサイズを変更する。*/
        if( (size + MALLOC_HEADSIZE + 16) < size2 ){
	    /* ブロックを再分割する必要がある場合 */
	    /*
            malloc_st_ptr->next
	      = (unsigned int *)((unsigned int)ptr + size + MALLOC_HEADSIZE);
	      */
            malloc_st_ptr->next
	      = (unsigned int *)((unsigned int)ptr + size) ;
            malloc_st_ptr->size = size;
    
            malloc_st_ptr = (struct mallocST *)malloc_st_ptr->next;
            malloc_st_ptr->next = next2;
            malloc_st_ptr->size = size2 - size - MALLOC_HEADSIZE;
            malloc_st_ptr->flag = 0;
        }else{
	    /* ブロックを再分割する必要がない場合 (ブロックのサイズが
               確保しようとしているサイズと同じ大きさだった場合) */
            malloc_st_ptr->next = next2;
            malloc_st_ptr->size = size2;
        }
	osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
        return  ptr;
    }
}