/* > m_alloc.c

 * SJ Middleton, 1993

 */

#include "kernel.h"
#include "os.h"
#include "swis.h"
#include "werr.h"
#include "msgs.h"

#include <stddef.h>
#include <string.h>

#include "memalloc.h"
#include "mem_int.h"

enum
{
        OSModule_Claim = 6,
        OSModule_Free,
        OSModule_ExtendBlock = 13
};

#if 0
BOOL m_alloc(void **addr, size_t nbytes)
{
        _kernel_swi_regs        r;
        _kernel_oserror         *e;

        if (*addr)
        {
                r.r[0] = OSModule_ExtendBlock;
                r.r[2] = (int) *addr;
                r.r[3] = nbytes - (((int *)*addr)[-1] - 8);
        }
        else
        {
                r.r[0] = OSModule_Claim;
                r.r[3] = nbytes;
        }

        e = _kernel_swi(OS_Module, &r, &r);

        if (e == NULL)
        {
                *addr = (void *)r.r[2];
                return TRUE;
        }

        os_err((os_error *)e);
        alloc__checkerror(nbytes);

        return FALSE;
}

void m_free(void **addr)
{
        if (*addr)
        {
                _kernel_swi_regs        r;
                r.r[0] = OSModule_Free;
                r.r[2] = (int) *addr;
                os_err((os_error *)_kernel_swi(OS_Module, &r, &r));
                *addr = NULL;
        }
}

#else

/*
 * Thisa allocator now stores the the area description
 * at the start of the allocated block to aid in tracking
 * down unfreed RMA blocks.
 * As with d_alloc if no area name is given it will use the
 * task name from msgs
 *
 * The exact structure is:
 * Offset Description
 *      +0              descriptor string (null-terminated)
 *                      word align
 *      +n              length of header in words (includes this word)
 *      +n+4    actual data (value returned to caller)

 * Note the calculation for the block size change in a bit nasty.

 * It is the new desired size - the old size (both including the descriptor).

 * The word before the returned ptr from OSModule_Alloc is the
 * total allocated size of the heap block, including 8 bytes
 * of header.
 */

BOOL m_alloc(void **addr, size_t nbytes)
{
        os_error        *e;
        void            *ptr;
        if (*addr)
        {
                int *iptr = *addr;
                int msglen = iptr[-1];

                iptr -= msglen;
                e = os_ModuleAlloc(OSModule_ExtendBlock,
                                iptr,
                                nbytes + msglen*4 - (iptr[-1] - 8),
                                &ptr);

                if (e == NULL)
                        ptr = (int *)ptr + msglen;
        }
        else
        {
                const char *msg = memalloc__nextareaname ? memalloc__nextareaname : (const char *)msgs_lookup("_TaskName");
                int     msglen = (strlen(msg) + 1 + 3) / 4 + 1;

                e = os_ModuleAlloc(OSModule_Claim,
                                NULL,
                                nbytes + msglen*4,
                                &ptr);

                if (e == NULL)
                {
                        int *iptr;
                        strcpy(ptr, msg);

                        iptr = (int *)ptr + msglen;
                        iptr[-1] = msglen;
                        ptr = iptr;
                }
        }

        alloc_nextiscalled(NULL);               /* clear name so it's not reused */
        alloc_nextmaxsize(-1);

        if (e == NULL)
        {
                *addr = ptr;
                return TRUE;
        }

        os_err(e);
        alloc__checkerror(nbytes);

        return FALSE;
}

void m_free(void **addr)
{
        if (*addr)
        {
                int *iptr = *addr;
                iptr -= iptr[-1];
                os_err(os_ModuleAlloc(OSModule_Free, iptr, 0, NULL));
                *addr = NULL;
        }
}

#endif

/* eof m_alloc.c */
