Menu

#507 Windows 2.0 freeze

fixed_in_git
open
nobody
None
5
2013-11-18
2013-11-14
No

With the fix for bug ticket #506,
Windows 2.0 goes further and loads correctly.
The Executive operates normally,
but when a Windows application is run,
DOSEMU print the error msg:
"ERRROR: SMALLOC: bad pointer passed to smget_area_size()",
and Windows 2.0 seems to hang (with hourglass showed).

The msg error appears when win.com calls EMS AH=51h
reallocate pages. I guess then there's probably
a bug remaining in reallocate_pages() in emm.c ...

Discussion

  • Eric Larouche

    Eric Larouche - 2013-11-15

    Here is the boot.log with only EMS
    debug trace enabled.

     
  • Eric Larouche

    Eric Larouche - 2013-11-15

    ...seems like Windows trying to reallocate the OS handle,
    which is mapped into conventional memory,
    thus producing the error message.
    I reproduced the err msg with a small test program.

    The OS handle is probably not treated properly
    in reallocate_pages() in emm.c
    (and for others funcs for that matter).
    What's the purpose of that special handle anyway?

    But I don't know if that would solve Windows
    not responding if reallocate was changed.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-15

    Are the changes in devel affect this anyhow?
    Please add another log in that case.
    Also, I bet the log is incomplete.
    Please do not truncate it.

    Yes, I am pretty sure fixing ems will get
    Windows to back work, because it used to work.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-15

    The purpose of the special handle is
    to map the conventional memory. It is
    described in the EMS specs.

    I think if windows is trying to reallocate
    it, then we have a bug, because I think
    we shouldn't return that handle at first
    place, and then windows will have no chance
    touching it.

     
  • Eric Larouche

    Eric Larouche - 2013-11-15

    Here is the complete boot.log (with EMS trace).

    According to the EMS spec,
    the OS handle (0) is preallocated and
    backfills the top 384K conventional memory
    on initialization. The spec says the OS
    may use the "reallocate pages"call
    to allocate more pages.

    The supplementary pages will be taken from
    expanded memory then? I guess the "logical map"
    for handle 0 is:
    top conventional mem 384K: logical pages 0-23
    expanded memory allocated: pages 24-...
    Is that correct?

    We should check with EMM386.exe to see how it behaves
    for this special handle.

     
  • Eric Larouche

    Eric Larouche - 2013-11-15

    I started to experiment with EMM386.exe
    and the OS handle.
    But I need to leave town for 2 days,
    and won't probably have Internet access.
    I'll get back to it on Monday.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-15

    I think it doesn't matter where the
    first 24 pages are allocated. They can
    as well be allocated in an expanded
    memory too.
    I think your question comes from the
    fact that dosemu is trying to keep the
    memory block contiguous, which would
    be impossible when you enlarge the os
    handle. I actually think this is a bug.
    Unless I am missing something, the space
    for logical pages is not needed to be
    virtually contiguous. You can do a per-page
    allocations. Without this, not only
    enlarging the os handle is impossible,
    but I guess also many other reallocs
    will step on each other's feets and fail
    for no reason.

     
  • Eric Larouche

    Eric Larouche - 2013-11-17

    Hi Stas,

    As for the first 24 allocated pages, they could be allocated in
    expanded memory indeed but that would waste 384K of physical memory.
    Also, in order not to corrupt DOS management of conventional memory
    (or TSR already present), I guess the EMM manager on initialization
    must either:
    1) use real conventional memory;
    2) or, make a copy of the 384k block into expanded memory before mapping.

    I believe your correct for the logical space. The backing store
    for the EMS logical space doesn't have to be virtually
    contiguous (as is the case in dosemu), since EMS apps
    only refer to individual logical page numbers,
    without knowledge of the implementation mechanism.

    Right now, dosemu can't enlarge the OS handle
    because of the contiguity constraint. I'm not sure of
    the best solution to this problem. At the top of my mind,
    I can think quickly of two possibilities:

    1) Treat the OS handle in a special way, but for other handles
    nothing changes. For the special handle, make object ptr points to
    supplementary allocated pages (>24) with the understanding that
    the first logical pages (up to 24) must point into LOWMEM.

    2) Remove the contiguity constraint altogether for all handles. Maybe have
    a global EMS memory pool for all handles and allocate logical pages on
    a per-page basis from it. That would imply though more management overhead.

    Option 1 is probably less drastic but option 2 more uniform. OTOH, I don't see why you say multiple reallocs could interfere with each other. Doesn't realloc move the block around if necessary?

    *
    

    I did experiment with MS-DOS EMM386, and it does work as I thought.
    The first 24 logical page (corresponding to backfilled conventional memory)
    can be remapped elsewhere in conv mem (logical pages 0-23 coincide
    with physical pages 4-27 initially) or in the page frame.
    Extending the OS handle, allow to map more pages into the physical space
    (in the 384K area or page frame).

     
  • Eric Larouche

    Eric Larouche - 2013-11-17

    ...third possibility:
    For the OS handle, allocate initially a 384K block
    for object and copy LOWMEM into it. Would be even better
    than option 1.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Yes, realloc can move, but that incurs
    the fragmentation. When you are fragmented
    enough, you may start having failures.
    dosemu gets away with that by not enforcing
    any limits on pool, which is not necessarily
    a right way.
    Also, when you realloc, you also need to
    unmap and then map again, so I don't see how
    the per-page allocations can have more
    management overhead. Clearly it is a smaller
    and faster code.

    I think you have refuted your "third possibility"
    already by correctly mentioning the waste of
    384K.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Yes, of course the code can be optimized
    to not require unmap/map cycles even with
    realloc (provided that realloc is trying
    to re-use the same physical store), but
    for what, if the entire realloc can be
    optimized out...

     
  • Eric Larouche

    Eric Larouche - 2013-11-18

    Ok, I didn't think realloc fragmentation was such a problem
    since the virtual address space is so large and EMS memory
    typically just uses a few megabytes at maximum.

    I agree using a single memory pool with per-page allocation
    would be cleaner and more in line with the EMS spec model.
    If realloc/remap could be eliminated, yes, there would be
    less dynamic overhead. But I think it would require a bit
    more code in emm.c though.

    Then, remains the question of the single memory
    pool implementation. A few possibilities:
    1) One global array allocation on init to the EMS mem maximum.
    Simple, but wasteful of memory if EMS isn't used much.

    2) A dynamic array. Less wasteful, but then we get back the
    realloc fragmentation issue (though probably less severe
    than multiple pools like the current implementation).

    3) A dynamic pool implemented as a linked-list of memory
    blocks with a reasonably coarse granularity for containing,
    let's say for example, about a hundred ems logical pages per block.
    Less wasteful of memory like 2 without the realloc overhead
    like 1. The downside is that the code logic would become a bit more
    complex.

    Any suggestion?

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Of course currently the fragmentation is
    not a big deal at all. But if it can be
    avoided alltogether with realloc and remap...

    Why not (at least for the first time) to
    not implement any pool, and just use a per-page
    allocations? In the handle_record struct you'll
    just transform "void object" into
    "void
    logical[MAX_LOGICAL_PAGES_PER_HANDLE]",
    or something along the lines. Looks like a
    trivial change mostly, or am I missing something?

     
  • Eric Larouche

    Eric Larouche - 2013-11-18

    Ah yes, per-page allocation would work also.
    It sure is the least invasive change.
    MAX_LOGICAL_PAGES_PER_HANDLE can be computed with max EMS memory
    and EMM_PAGE_SIZE. The logical array would require to be
    dynamically allocated though, because ems_size is not
    a compile-time constant.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    The standard says:

    BX = num_pages_alloc_to_emm_handle
    Contains the number of logical pages allocated to the
    specified EMM handle. This number never exceeds 2048
    because the memory manager allows a maximum of 2048 pages
    (32M bytes) of expanded memory.


    Whether or not we should trust that part,
    is however unclear... Surely the 65536 would
    be a definite limit, but that's too much for
    the static allocations.
    If you don't want to trust in a 2048 limit,
    then I will suggest to use glib... It was not
    used in dosemu before AFAIK, but someone have
    to start... :) I already had enough implementing
    the hand-made containers of different kind for
    dosemu.

     
  • Eric Larouche

    Eric Larouche - 2013-11-18

    This number never exceeds 2048
    because the memory manager allows a maximum of 2048 pages
    (32M bytes) of expanded memory.
    [...]
    Whether or not we should trust that part,
    is however unclear.

    Why shouldn't we trust the limit? The 32 MB max value
    seems to be a hard limit of the standard. It's clearly
    diagrammed at the beginning of the spec.
    2048 doesn't appear to me too much costly
    (16K on x64 and 8K on x32) per handle.

    As for using glib, in this specific case, you mean
    to make use of a dynamical array GPtrArray for example?

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Does dosemu already honour the limit of 32Mb total?
    If not, I would probably suggest against
    enforcing it, unless there are a big reason to.
    Is this limit enforced in emm386 and qemm?
    Of course if dosemu already has this limit,
    then no problems to keep it that way.

    Yes, something like GPtrArray, or in fact
    maybe GArray, because it is not unexpected
    if someone would also like to save other
    things, like, for instance, a number of the
    mapped physical page, for a faster lookups.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Actually no, we can't do it statically,
    no matter what. Your calculations are wrong
    in that you forgot to multiple per MAX_HANDLES.
    We need the size of the whole handle_info array.

     
  • Eric Larouche

    Eric Larouche - 2013-11-18

    I checked, and the 32 MB is not currently enforced in dosemu.
    However, emm386 doesn't support mem > 32 MB.
    I don't have qemm installed, so I can't check it.
    I'd say then that dosemu is just not standard-conformant
    at the moment.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    OK, IMHO the easiest way is to just
    realloc() the logicals array itself.
    Or use glib. Whatever you prefer. :)

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Ok, thanks for info.
    In fact, enforcing 2048 logicals doesn't
    limit us to 32Mb total, but to 32Mb per
    page, which would be fine... if it would
    help, but it doesn't.

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    per page = per handle, sorry

     
  • Eric Larouche

    Eric Larouche - 2013-11-18

    I started to change the code. Must of it is quite trivial.
    However, I just realized that it will complicate quite a bit
    the implementation for the Move/Exchange region EMS call,
    if the region crosses multiple logical pages
    (because of the lost of contiguity).
    It will require some type of scatter/gather functionality...

     
  • Stas Sergeev

    Stas Sergeev - 2013-11-18

    Argh. Indeed.
    Or you can create a temporary, contiguous
    mapping while copying.
    But I think s/g is not very difficult here,
    so likely the temporary mapping is too much
    just for that.

     

Log in to post a comment.