Exemplo n.º 1
0
/*
 * allocate the TPA
 *
 * we first determine if ST RAM and/or alternate RAM is available for
 * allocation, based on the flags, the amount of RAM required and
 * the presence or absence of TT RAM.
 *
 * if no types are available (the requested amount is too large), we
 * return NULL.
 *
 * if only one type of RAM is available, we allocate it & return a
 * pointer to it.
 *
 * if both types are available, we normally allocate in alternate RAM
 * *except* if the amount of ST RAM is greater than the amount of
 * alternate RAM.  In this case, we use a tiebreaker: bits 31-27
 * of the flags field plus 1 is taken as a 4-bit number, which is
 * multiplied by 128K and added to the base amount needed to get a
 * "would like to have" amount.  If this amount is larger than the
 * amount of alternate RAM, then we allocate in ST RAM.
 *
 * Reference: TT030 TOS Release Notes, Third Edition, 6 September 1991,
 * pages 29-30.
 *
 * returns: ptr to MD of allocated memory (NULL => failed)
 *          updates 'avail' with the size of allocated memory
 */
static MD *alloc_tpa(ULONG flags,LONG needed,LONG *avail)
{
    LONG st_ram_size;
    BOOL st_ram_available = FALSE;

    st_ram_size = (LONG) ffit(-1L, &pmd);
    if (st_ram_size >= needed)
        st_ram_available = TRUE;

#if CONF_WITH_ALT_RAM
    {
        LONG alt_ram_size = 0L, tpasize;
        BOOL alt_ram_available = FALSE;

        if (has_alt_ram && (flags & PF_TTRAMLOAD)) {
            alt_ram_size = (LONG) ffit(-1L, &pmdalt);
            if (alt_ram_size >= needed)
                alt_ram_available = TRUE;
        }

        if (st_ram_available && alt_ram_available && (st_ram_size > alt_ram_size)) {
            tpasize = (((flags >> 28) & 0x0f) + 1) * TPASIZE_QUANTUM;
            if (needed+tpasize > alt_ram_size)
                alt_ram_available = FALSE;  /* force allocation in ST RAM */
        }

        if (alt_ram_available) {
            *avail = alt_ram_size;
            return ffit(alt_ram_size, &pmdalt);
        }
    }
Exemplo n.º 2
0
/* allocate the environment, always in ST RAM */
static MD *alloc_env(char *env)
{
    MD *env_md;
    int size;

    /* determine the env size */
    if (env == NULL)
        env = run->p_env;
    size = (envsize(env) + 1) & ~1;  /* must be even */

    /* allocate it */
    env_md = ffit((long) size, &pmd);
    if (env_md == NULL)
        return NULL;

    /* copy it */
    memcpy(env_md->m_start, env, size);

    return env_md;
}
Exemplo n.º 3
0
long    xmxalloc(long amount, int mode)
{
    MD *m;
    long ret_value;

#if DBGUMEM
    kprintf("BDOS: xmxalloc(%ld, %d)\n", amount, mode);
#endif

    /*
     * if amount == -1L, return the size of the biggest block
     * 
     */
    if(amount == -1L) {
        switch(mode) {
        case MX_STRAM:
            ret_value = (long) ffit(-1L,&pmd);
            break;
#if CONF_WITH_ALT_RAM
        case MX_TTRAM:
            ret_value = (long) ffit(-1L,&pmdalt);
            break;
#endif
        case MX_PREFSTRAM:
        case MX_PREFTTRAM:
            /* TODO - I assume that the correct behaviour is to return
             * the biggest size in either pools. The documentation is unclear.
             */ 
            {
                ret_value = (long) ffit(-1L,&pmd);
#if CONF_WITH_ALT_RAM
                {
                    long tmp = (long) ffit(-1L,&pmdalt);
                    if(ret_value < tmp) ret_value = tmp;
                }
#endif
            }
            break;
        default:
            /* unknown mode */
            ret_value = 0;
        }
        goto ret;
    }

    /* 
     * return NULL if asking for a negative or null amount
     */

    if( amount <= 0 ) {
        ret_value = 0;
        goto ret;
    }

    /*
     * Pass the request on to the internal routine. 
     */

    switch(mode) {
    case MX_STRAM:
        m = ffit(amount,&pmd);
        break;
#if CONF_WITH_ALT_RAM
    case MX_TTRAM:
        m = ffit(amount,&pmdalt);
        break;
#endif
    case MX_PREFSTRAM:
        m = ffit(amount,&pmd);
#if CONF_WITH_ALT_RAM
        if(m == NULL) 
            m = ffit(amount,&pmdalt);
#endif
        break;
    case MX_PREFTTRAM:
#if CONF_WITH_ALT_RAM
        m = ffit(amount,&pmdalt);
        if(m == NULL) 
#endif
            m = ffit(amount,&pmd);
        break;
    default:
        /* unknown mode */
        m = 0;
    }

    /*
     * The internal routine returned a pointer to a memory descriptor, or NULL
     * Return its pointer to the start of the block.
     */

    if(m == NULL) {
        ret_value = 0;
    } else {
        ret_value = (long) m->m_start;
    }

ret:
#if DBGUMEM
    kprintf("BDOS: xmxalloc returns 0x%08lx\n", ret_value);
    dump_mem_map();
#endif

    return(ret_value);
}
Exemplo n.º 4
0
/*
 *  xmxalloc - Function 0x44 (Mxalloc)
 */
void *xmxalloc(long amount, int mode)
{
    MD *m;
    void *ret_value;

    KDEBUG(("BDOS: xmxalloc(%ld,0x%04x)\n",amount,mode));

    mode &= MX_MODEMASK;    /* ignore unsupported bits */

    /*
     * if amount == -1L, return the size of the biggest block
     *
     */
    if (amount == -1L) {
        switch(mode) {
        case MX_STRAM:
            ret_value = ffit(-1L,&pmd);
            break;
#if CONF_WITH_ALT_RAM
        case MX_TTRAM:
            ret_value = ffit(-1L,&pmdalt);
            break;
#endif
        case MX_PREFSTRAM:
        case MX_PREFTTRAM:
            /*
             * for the "preferred" options, the correct behaviour is to
             * return the biggest size in either pool - verified on TOS3
             */
            {
                ret_value = ffit(-1L,&pmd);
#if CONF_WITH_ALT_RAM
                {
                    void *tmp = ffit(-1L,&pmdalt);
                    if (ret_value < tmp)
                        ret_value = tmp;
                }
#endif
            }
            break;
        default:
            /* unknown mode */
            ret_value = NULL;
        }
        goto ret;
    }

    /*
     * return NULL if asking for a negative or null amount
     */
    if (amount <= 0) {
        ret_value = NULL;
        goto ret;
    }

    /*
     * Pass the request on to the internal routine.
     */
    switch(mode) {
    case MX_STRAM:
        m = ffit(amount,&pmd);
        break;
#if CONF_WITH_ALT_RAM
    case MX_TTRAM:
        m = ffit(amount,&pmdalt);
        break;
#endif
    case MX_PREFSTRAM:
        m = ffit(amount,&pmd);
#if CONF_WITH_ALT_RAM
        if (m == NULL)
            m = ffit(amount,&pmdalt);
#endif
        break;
    case MX_PREFTTRAM:
#if CONF_WITH_ALT_RAM
        m = ffit(amount,&pmdalt);
        if (m == NULL)
#endif
            m = ffit(amount,&pmd);
        break;
    default:
        /* unknown mode */
        m = NULL;
    }

    /*
     * The internal routine returned a pointer to a memory descriptor, or NULL
     * Return its pointer to the start of the block.
     */
    if (m == NULL) {
        ret_value = NULL;
    } else {
        ret_value = m->m_start;
    }

ret:
    KDEBUG(("BDOS xmxalloc: returns 0x%08lx\n",(ULONG)ret_value));
    dump_mem_map();

    return ret_value;
}
Exemplo n.º 5
0
long xexec(WORD flag, char *path, char *tail, char *env)
{
    PD *p;
    PGMHDR01 hdr;
    MD *m, *env_md;
    LONG rc;
    long max, needed;
    FH fh;

    D(("BDOS: xexec - flag or mode = %d\n", flag));

    /* first branch - actions that do not require loading files */
    switch(flag) {
    case PE_RELOCATE: 
        p = (PD *) tail;
        rc = kpgm_relocate(p, (long)path);
        if(rc) {
            D(("BDOS: xexec - kpgm_relloc returned %ld (0x%lx)\n", rc, rc));
            return(rc);
        }

        /* invalidate instruction cache for the TEXT segment only
         * programs that jump into their DATA, BSS or HEAP are kindly invited 
         * to do their cache management themselves.
         */
        invalidate_icache( p+1, p->p_tlen);

        return (long) p;
    case PE_BASEPAGE:        
        /* just create a basepage */
        env_md = alloc_env(env);
        if(env_md == NULL) {
            D(("xexec: Not Enough Memory!\n"));
            return(ENSMEM);
        }
        max = (long) ffit(-1L, &pmd); 
        if(max >= sizeof(PD)) {
            m = ffit(max, &pmd);
            p = (PD *) m->m_start;
        } else {
            /* not even enough memory for basepage */
            freeit(env_md, &pmd);
            D(("xexec: No memory for TPA\n"));
            return(ENSMEM);
        }
        /* memory ownership */
        m->m_own = env_md->m_own = run;

        /* initialize the PD */
        init_pd_fields(p, tail, max, env_md);
        init_pd_files(p);

        return (long) p;
    case PE_GOTHENFREE:
        /* set the owner of the memory to be this process */
        p = (PD *) tail;
        set_owner(p, p, find_mpb(p));
        set_owner(p->p_env, p, find_mpb(p->p_env));
        /* fall through */
    case PE_GO:
        p = (PD *) tail;
        proc_go(p);
        /* should not return ? */
        return (long)p;
    case PE_LOADGO:
    case PE_LOAD:
        break;
    default:
        return EINVFN;
    }
    
    /* we now need to load a file */
    D(("BDOS: xexec - trying to find the command ...\n"));
    if (ixsfirst(path,0,0L)) {
        D(("BDOS: Command %s not found!!!\n", path));
        return(EFILNF);     /*  file not found      */
    }

    /* load the header - if IO error occurs now, the longjmp in rwabs will
     * jump directly back to bdosmain.c, which is not a problem because
     * we haven't allocated anything yet.
     */
    rc = kpgmhdrld(path, &hdr, &fh);
    if(rc) {
        D(("BDOS: xexec - kpgmhdrld returned %ld (0x%lx)\n", rc, rc));
        return(rc);
    }

    /* allocate the environment first, always in ST RAM */
    env_md = alloc_env(env);
    if ( env_md == NULL ) {
        D(("xexec: Not Enough Memory!\n"));
        return(ENSMEM);
    }
    
    /* allocate the basepage depending on memory policy */
    needed = hdr.h01_tlen + hdr.h01_dlen + hdr.h01_blen + sizeof(PD);
    max = 0;
        
    /* first try */
    p = NULL;
    m = NULL;
#if CONF_WITH_ALT_RAM
    if(has_alt_ram && (hdr.h01_flags & PF_TTRAMLOAD)) {
        /* use alternate ram preferably */
        max = (long) ffit(-1L, &pmdalt); 
        if(max >= needed) {
            m = ffit(max, &pmdalt);
            p = (PD *) m->m_start;
        } 
    }
#endif
    /* second try */
    if(p == NULL) {
        max = (long) ffit(-1L, &pmd); 
        if(max >= needed) {
            m = ffit(max, &pmd);
            p = (PD *) m->m_start;
        } 
    }
    /* still failed? free env_md and return */
    if(p == NULL) {
        D(("xexec: No memory for TPA\n"));
        freeit(env_md, &pmd);
        return(ENSMEM);
    }
    assert(m != NULL);

    /* memory ownership - the owner is either the new process being created,
     * or the parent 
     */
    if(flag == PE_LOADGO) {
        m->m_own = env_md->m_own = p;
    } else {
        m->m_own = env_md->m_own = run;
    }   

    /* initialize the fields in the PD structure */
    init_pd_fields(p, tail, max, env_md);
    
    /* set the flags (must be done after init_pd) */
    p->p_flags = hdr.h01_flags;

    /* use static variable to avoid the obscure longjmp warning */
    cur_p = p;
    cur_m = m;
    cur_env_md = env_md;

    /* we have now allocated memory, so we need to intercept longjmp. */
    memcpy(bakbuf, errbuf, sizeof(errbuf));
    if ( setjmp(errbuf) ) {

        kprintf("Error and longjmp in xexec()!\n");

        /* free any memory allocated yet */
        freeit(cur_env_md, &pmd);
        freeit(cur_m, find_mpb((void *)cur_m->m_start));
        
        /* we still have to jump back to bdosmain.c so that the proper error
         * handling can occur.
         */
        longjmp(bakbuf, 1);
    }

    /* now, load the rest of the program and perform relocation */
    rc = kpgmld(cur_p, fh, &hdr);
    if ( rc ) {
        D(("BDOS: xexec - kpgmld returned %ld (0x%lx)\n", rc, rc));
        /* free any memory allocated yet */
        freeit(cur_env_md, &pmd);
        freeit(cur_m, find_mpb((void *)cur_m->m_start));
    
        return rc;
    }

    /* at this point the program has been correctly loaded in memory, and 
     * more IO errors cannot occur, so it is safe now to finish initializing
     * the new process.
     */
    init_pd_files(cur_p);
    
    /* invalidate instruction cache for the TEXT segment only
     * programs that jump into their DATA, BSS or HEAP are kindly invited 
     * to do their cache management themselves.
     */
    invalidate_icache(((char *)cur_p) + sizeof(PD), hdr.h01_tlen);

    if(flag != PE_LOAD)
        proc_go(cur_p);
    return (long) cur_p;
}