To me, the documentation is most likely no longer true, I see no reason why
the memory need to be movable, and nondiscardable/discardable have no
meaning for GlobalAlloc in Win32. We have done quite a lot of tests with
using GMEM_FIXED, everything so far works perfectly well. But still, we are
not follow the document, can someone knows the internals explain why the
handle must be movable, if it's not a documentation issue.
Thanks,
Wenjin
If you are the only user of Memory-Streams and the only caller of
GlobalAlloc in your process,
(BTW, are you building a server with many cross apartment
communication or are you building a UI application wuth a lot of clipboard
operation),
it may work for your application.
I can build a small test case where the lack of GMEM_FIXED
would corrupt the user mode handle-table.
You may considere writing your-own IStream implementation,
if that fits the requirements of your application.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
"Wenjin Zhang" <zhan...@hotmail.com> wrote in message
news:e3g6QKBm...@TK2MSFTNGP09.phx.gbl...
I know the process heap is locked when GlobalAlloc is called, with and
without GMEM_FIXED. Our application doesn't call GlobalAlloc and
CreateStreamOnHGlobal very often, but once we get the IStream pointer, the
application reads the stream (generally there is no write) very frequently,
and often with small sizes. It seems calling IStream->Read causes a critical
section been locked, after the content been copied over, then the critical
section is unlocked. The problem is, it seems that's a global critical
section - one per process. Therefore, even different threads use different
IStream pointers (created on different global memory handles), they are
fighting for the same lock. My guess is that with GMEM_FIXED, IStream->Read
doesn't try to obtain a global lock.
Just roughly looked the API HeapWalk, it seems the GMEM_MOVEABLE is
implemented with the corporation of heap management and module managing the
local handle-table. My guess is that the critical section mentioned above is
the lock of the process heap. When a memory (allocated with GEME_MOVEABLE)
is locked, Windows updates the handle-table, but other than that, it seems
also lock the process heap and update the element flag. Memory allocated
with GMEM_FIXED is allocated from process heap directly, so even the
IStream->Read calls GlobalLock/GlobalUnlock, nothing actually changed, at
least there is no lock/unlock.
Also I don't quite understand why the GMEM_MOVEABLE is still necessary. I
know GlobalRealloc only grow fixed memory in place, but realloc-and-copy
should solve that problem. The description of GetHGlobalFromStream indicates
that the handle could change, so that doesn't break the existing contract.
We could reduce the contention by adding another layer of buffering (for
IStream->Read), but that looks weird because then we buffer memory with
memory.
Wenjin
"Ivan Brugiolo [MSFT]" <ivan...@online.microsoft.com> wrote in message
news:%23B%23AgGCm...@TK2MSFTNGP09.phx.gbl...
I know the process heap is locked when GlobalAlloc is called, with and
without GMEM_FIXED. Our application doesn't call GlobalAlloc and
CreateStreamOnHGlobal very often, but once we get the IStream pointer, the
application reads the stream (generally there is no write) very frequently,
and often in small sizes. It seems calling IStream->Read causes a critical
section been locked, after the content been copied over, then the critical
section is unlocked. The problem is, it seems that's a global critical
section - one per process. Therefore, even different threads use different
IStream pointers (created on different global memory handles), they are
fighting for the same lock. My guess is that with GMEM_FIXED, IStream->Read
doesn't try to obtain a global lock.
Just roughly looked the API HeapWalk, it seems the GMEM_MOVEABLE is
implemented with the corporation of heap management and module managing the
local handle-table. My guess is that the critical section mentioned above is
the lock of the process heap. When a memory (allocated with GEME_MOVEABLE)
is locked, Windows updates the handle-table, but other than that, it seems
also lock the process heap and update the element flag. Memory allocated
with GMEM_FIXED is allocated from process heap directly, so even the
IStream->Read calls GlobalLock/GlobalUnlock, nothing actually changes, at
least there is no lock/unlock.
Also I don't quite understand why the GMEM_MOVEABLE is still necessary. I
know GlobalRealloc only grow fixed memory in place, but realloc-and-copy
should solve that problem. The description of GetHGlobalFromStream indicates
that the handle could change, so that doesn't break the existing contract.
We could reduce the contention by adding another layer of buffering (for
IStream->Read), but that looks weird because then we buffer memory with
memory.
Wenjin
"Ivan Brugiolo [MSFT]" <ivan...@online.microsoft.com> wrote in message
news:%23B%23AgGCm...@TK2MSFTNGP09.phx.gbl...
LockHeap(hHeap);
hEntry = GetHandle();
p = HeapAlloc(hHeap,HEAP_NO_SERIALIZE,size);
UnlockHeap(hHeap);
while the regular heap code does the locking internalli in ntdll.dll
all the times the HEAP_NO_SERIALIZE flag is NOT specified.
The critical section you are seeing is the lock of the process heap,
(if you look at the address of the critical section and the heap handle,
you should convince yourself of that)
used implicitely or explicitely in many several code-paths.
What does in your applicaiton mandates the use
of the IStream created by the CreateStreamOnHGlobal ?
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
"Wenjin Zhang" <zhan...@hotmail.com> wrote in message
news:#r64DjCm...@TK2MSFTNGP09.phx.gbl...
hMem = GlobalAlloc(GMEM_FIXED, ulLength); // we used to use
GEME_MOVEABLE
hr = CreateStreamOnHGlobal(hMem, TRUE, &m_pStream);
hr = m_pStream->Write (bStream, ulLength, &bytesRead);
After initialized the m_pStream, our application access the content very
frequently (mainly read by calling m_pStream->Read). The problem is,
If we allocate memory with GEME_MOVEABLE , it seems m_pStream->Read causes a
critical section (it's a per process lock) been locked and then unlocked,
even different threads are using different m_pStream. We are running tests
on a 8 processor machine, the single critical section basically puts access
to different streams into a queue, so the CPU usage is always very low.
We use IStream created by the CreateStreamOnHGlobal mainly because we want
to have same interface, no matter where the contents come from.
"Ivan Brugiolo [MSFT]" <ivan...@online.microsoft.com> wrote in message
news:ucolnHDm...@TK2MSFTNGP09.phx.gbl...
hMem = GlobalAlloc(GMEM_FIXED, ulLength); // we used to use
GEME_MOVEABLE
hr = CreateStreamOnHGlobal(hMem, TRUE, &m_pStream);
hr = m_pStream->Write (bStream, ulLength, &bytesRead);
After initialized the m_pStream, our application access the content very
frequently (mainly read by calling m_pStream->Read). The problem is,
If we allocate memory with GEME_MOVEABLE , it seems m_pStream->Read causes a
critical section (it's a per process lock) been locked and then unlocked,
even different threads are using different m_pStream. We are running tests
on a 8 processor machine, the single critical section basically puts access
to different streams into a queue, so the CPU usage is always very low.
We use IStream created by the CreateStreamOnHGlobal mainly because we want
to have same interface, no matter where the contents come from.
"Ivan Brugiolo [MSFT]" <ivan...@online.microsoft.com> wrote in message
news:ucolnHDm...@TK2MSFTNGP09.phx.gbl...
I can't comment officially (only MSFT can do that), but from what I can
determine, your analysis of the situation is exactly correct. I believe
that the requirement for GMEM_MOVEABLE is a leftover from 16-bit OLE and has
no relevance in a Win32 app.
-cd
You should really consider your own implementation of IStream.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
"Wenjin Zhang" <zhan...@hotmail.com> wrote in message
news:ulzyXeDm...@TK2MSFTNGP10.phx.gbl...
We would all be happy to deprecate the GlobalXXX and LocalXXX API,
but there's too much existing software that relay on subtle behaviors,
and components in the same process may not interoperate if you change that.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
"Wenjin Zhang" <zhan...@hotmail.com> wrote in message
news:#8ZAmXEm...@TK2MSFTNGP10.phx.gbl...
GMEM_MOVEABLE
If GMEM_MODIFY is also specified, GMEM_MOVEABLE changes a fixed memory
object to a movable memory object.
If GMEM_MODIFY is not specified, then GMEM_MOVEABLE allows a locked
GMEM_MOVEABLE memory block or a GMEM_FIXED memory block to be moved to a new
fixed location. If neither GMEM_MODIFY nor GMEM_MOVEABLE is set, then fixed
memory blocks and locked movable memory blocks will only be reallocated in
place.
A fix memory is returned because the IStream::Write calls GlobalRealloc with
GMEM_MOVEABLE, which explains why even write is safe.
If my findings are valid on all platforms and are consistent with the source
code, perhaps Microsoft can update the OLE document in the future.
"Ivan Brugiolo [MSFT]" <ivan...@online.microsoft.com> wrote in message
news:ep6QEZGm...@tk2msftngp13.phx.gbl...
"Wenjin Zhang" <zhan...@hotmail.com> wrote in message
news:uXvU3pMm...@tk2msftngp13.phx.gbl...
Remarks
The handle this function returns may be different from the original handle
due to intervening GlobalRealloc calls.
My test app gets back the handle with GetHGlobalFromStream after it grows
the stream, when the memory is initially allocated with GMEM_FIXED,
GetHGlobalFromStream returns a handle different from the one passed to
CreateStreamOnHGlobal, but both are handles of fixed memory.
Wenjin
"Raymond Chen" <http://blogs.gotdotnet.com/raymondc/> wrote in message
news:O6gVnCRm...@TK2MSFTNGP10.phx.gbl...