Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What is thread-safe in the Windows API?

1,036 views
Skip to first unread message

Enquiring Mind

unread,
Jul 2, 2008, 10:35:57 AM7/2/08
to
Hi,

When Farshad pointed out that the ReadFile and WriteFile API functions are
not thread-safe, I asked myself whether *any* API functions are
thread-safe. I also wondered what operations and data types can be
considered atomic and therefore thread-safe. Is a simple operation like
calling TEvent.ResetEvent thread-safe because it involves setting the value
of an unsigned integer or a Boolean? Is the function GetLastError
thread-safe, because it only reads an atomic data type? Is an assignment to
a double-precision variable thread-safe? Are all Get and Put operations on
pointers thread-safe because the data type is a 4-byte cardinal? Is calling
a property that internally sets an integer not thread-safe because a method
call might not be thread-safe?

TiA for any guidance,

EM


Remy Lebeau (TeamB)

unread,
Jul 2, 2008, 1:55:47 PM7/2/08
to

"Enquiring Mind" <Enquiri...@nospam.btopenworld.com> wrote in message
news:486b...@newsgroups.borland.com...

> When Farshad pointed out that the ReadFile and WriteFile API
> functions are not thread-safe, I asked myself whether *any* API
> functions are thread-safe.

It depends on the API. Some are, some are not.

> I also wondered what operations and data types can be
> considered atomic and therefore thread-safe.

32-bit integers that are properly aligned on 32-bit memory boundaries can be
accessed atomically. Anything else is not atomic. Best to use the Win32
API's Interlocked...() functions when atomic access is needed. Don't rely
on implicit atomic access.

> Is a simple operation like calling TEvent.ResetEvent thread-safe
> because it involves setting the value of an unsigned integer or a
> Boolean?

That is not what TEvent.ResetEvent() does.

Even accessing a simple integer is not thread-safe if the variable is not
aligned in memory properly. Misaligned integers can't be accessed
atomically.

> Is the function GetLastError thread-safe

Yes. The error code is stored in TLS (thread-local storage) memory on a
per-thread basis. GetLastError() and SetLastError() access the appropriate
TLS slot for the calling thread. If multiple threads call GetLastError() at
the same time, they access different memory addresses, and thus cannot step
over each other.

> because it only reads an atomic data type?

That is not what GetLastError() does.

> Is an assignment to a double-precision variable thread-safe?

No.

> Are all Get and Put operations on pointers thread-safe
> because the data type is a 4-byte cardinal?

Not if they are misaligned.

> Is calling a property that internally sets an integer not
> thread-safe because a method call might not be thread-safe?

Yes.


Gambit


AlexB

unread,
Jul 3, 2008, 12:15:00 AM7/3/08
to
Remy Lebeau (TeamB) wrote:

> 32-bit integers that are properly aligned on 32-bit memory boundaries
> can be accessed atomically.

Could you confirm it for miltiprocessor systems too ?
What about 16-bit alignment for words ?

--
Alex

Martin James

unread,
Jul 3, 2008, 12:49:50 AM7/3/08
to

"Enquiring Mind" <Enquiri...@nospam.btopenworld.com> wrote in message
news:486b...@newsgroups.borland.com...
> Hi,
>
> When Farshad pointed out that the ReadFile and WriteFile API functions are
> not thread-safe,
Eh? ReadFile and WriteFile API functions are not thread-safe?

I frequently have many apps reading and writing files 'simultaneously'. I
can save a file in Word while BitTorrent is downloading err.
non-copyrighted, non-porn, data and saving it to files.

A check with the task manager shows these Windows systems/services that are
frequently involved with reading/writing files:

explorer.exe: 17 threads
scvhost.exe:74 threads
Mcshield: 37 threads

There are dozens of other processes running, most with more than one thread.

How can filesystem APIs not be thread-safe??

>I asked myself whether *any* API functions are thread-safe.

Windows is a multiprocessor, multitasking OS. Of course the vast majority
of APIs are thread-safe. If you try, you can cause problems with multiple
threads by using the APIs in an unreasonable manner but, on the whole, *the
APIs must be thread safe else Windows would only be able to run one process
with one thread at a time*. If the APIs were not thread-safe, the MTBF for
Windows would be in the order of milliseconds. You would never see your
desktop because a crash/BSOD would happen first.

There are some high-level APIs that are not thread-safe - ones concerned
with the debugger, for example. These speicalist API calls are explicitly
declared in such a manner on MSDN because they are *rare, special-purpose
exceptions to an obvious general rule that APIs on multitasking systems must
be thread-safe*.

Rgds,
Martin

Enquiring Mind

unread,
Jul 3, 2008, 9:29:41 AM7/3/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:486bc2a0$1...@newsgroups.borland.com...

> 32-bit integers that are properly aligned on 32-bit memory boundaries can
> be accessed atomically. Anything else is not atomic. Best to use the
> Win32 API's Interlocked...() functions when atomic access is needed.
> Don't rely on implicit atomic access.
>
Are the only variables that are not aligned on 32-bit memory boundaries
fields of packed records or components of packed arrays? I presume that by
default all variables and structure members are compiled to be aligned to
32-bit memory boundaries, unless the predefined data type is automatically
packed (e.g. the string type).

>> Is a simple operation like calling TEvent.ResetEvent thread-safe
>> because it involves setting the value of an unsigned integer or a
>> Boolean?
>
> That is not what TEvent.ResetEvent() does.

I don't know what the method does in detail, but I thought that end effect
is to set the Signaled property to False.


>
> Yes. The error code is stored in TLS (thread-local storage) memory on a
> per-thread basis. GetLastError() and SetLastError() access the
> appropriate TLS slot for the calling thread. If multiple threads call
> GetLastError() at the same time, they access different memory addresses,
> and thus cannot step over each other.
>

Thanks for that insight.

>> because it only reads an atomic data type?
>
> That is not what GetLastError() does.

Whatever else GetLastError does internally, from the perspective of the
application program it appears to retrieve the value of an integer variable
owned by the OS.


>
>> Are all Get and Put operations on pointers thread-safe
>> because the data type is a 4-byte cardinal?
>
> Not if they are misaligned.
>

When could a pointer variable be misaligned? When it's the member of a
packed record or array? BTW, can objects be packed?

>> Is calling a property that internally sets an integer not
>> thread-safe because a method call might not be thread-safe?
>
> Yes.
>

Just to clarify, are you saying that the mechanics of calling a procedure or
function (i.e. allocating a context framework on the stack) is not thread
safe? This would imply that any property that uses a Getter method to return
the value of an atomic data type would not be thread-safe.

Regards,

EM


Enquiring Mind

unread,
Jul 3, 2008, 9:41:59 AM7/3/08
to

"Martin James" <nos...@tuthill.com> wrote in message
news:486c5a6c$1...@newsgroups.borland.com...

>
> Eh? ReadFile and WriteFile API functions are not thread-safe?
>
> I frequently have many apps reading and writing files 'simultaneously'.

I was referring to concurrent reading and writing to the same file
(representing a serial port), not concurrent I/O operations on different
files.

> How can filesystem APIs not be thread-safe??

What I thought might not be thread-safe is to call ReadFile in one thread
and WriteFile in another on the same file.


>
> Windows is a multiprocessor, multitasking OS. Of course the vast majority
> of APIs are thread-safe. If you try, you can cause problems with multiple
> threads by using the APIs in an unreasonable manner but, on the whole,
> *the APIs must be thread safe else Windows would only be able to run one
> process with one thread at a time*. If the APIs were not thread-safe,
> the MTBF for Windows would be in the order of milliseconds. You would
> never see your desktop because a crash/BSOD would happen first.
>

That's most reassuring! So there's no need after all to wrap API I/O calls
in critical sections, mutexes, etc. Windows does that for you under the
hood. Is that right?

> There are some high-level APIs that are not thread-safe - ones concerned
> with the debugger, for example. These speicalist API calls are explicitly
> declared in such a manner on MSDN because they are *rare, special-purpose
> exceptions to an obvious general rule that APIs on multitasking systems
> must be thread-safe*.
>

Where can I find a clear statement in the MS documentation about what in the
API is, and isn't, thread safe?

Regards,

EM


Remy Lebeau (TeamB)

unread,
Jul 3, 2008, 2:01:53 PM7/3/08
to

"Enquiring Mind" <Enquiri...@nospam.btopenworld.com> wrote in message
news:486cd446$1...@newsgroups.borland.com...

> Just to clarify, are you saying that the mechanics of calling a
> procedure or function (i.e. allocating a context framework
> on the stack) is not thread safe?

That portion of a procedure/function call is always thread-safe. But once
the stack frame is set up and the main body of the code is actually running,
the code is not thread-safe if it accesses memory that is shared with other
threads without using proper synchronization.


Gambit


Adem

unread,
Jul 3, 2008, 2:34:49 PM7/3/08
to
Remy Lebeau (TeamB) wrote:

> Even accessing a simple integer is not thread-safe if the variable is
> not aligned in memory properly. Misaligned integers can't be
> accessed atomically.

Just out of curiosity, how can one tell whether a variable is aligned
in memory properly or not?

Remy Lebeau (TeamB)

unread,
Jul 3, 2008, 6:18:57 PM7/3/08
to

"Adem" <adem...@gmail.com> wrote in message
news:486d1bc9$1...@newsgroups.borland.com...

> Just out of curiosity, how can one tell whether a variable
> is aligned in memory properly or not?

For 32-bit CPUs, does the variable exist at a memory address that is evenly
divisible by 4?


Gambit


Martin James

unread,
Jul 4, 2008, 12:47:01 AM7/4/08
to
>
> I was referring to concurrent reading and writing to the same file
> (representing a serial port), not concurrent I/O operations on different
> files.

Reading the COM ports from one thread and writing from another is fine. I
have been doing that for decades. If it is now not OK, eg. because M$ have
broken the COM ports on multiProcessor architectures, or on Vista, then I
have not heard about it.

>> How can filesystem APIs not be thread-safe??
>
> What I thought might not be thread-safe is to call ReadFile in one thread
> and WriteFile in another on the same file.

That is an operation that is difficult to understand on a block-oriented
device like a real disk file. On a stream-oriented device like a COM port,
it's fine.

>> Windows is a multiprocessor, multitasking OS. Of course the vast
>> majority of APIs are thread-safe. If you try, you can cause problems
>> with multiple threads by using the APIs in an unreasonable manner but, on
>> the whole, *the APIs must be thread safe else Windows would only be able
>> to run one process with one thread at a time*. If the APIs were not
>> thread-safe, the MTBF for Windows would be in the order of milliseconds.
>> You would never see your desktop because a crash/BSOD would happen first.
>>
> That's most reassuring! So there's no need after all to wrap API I/O calls
> in critical sections, mutexes, etc. Windows does that for you under the
> hood. Is that right?

Yes - it has to. There is no sane alternative.

>> There are some high-level APIs that are not thread-safe - ones concerned
>> with the debugger, for example. These speicalist API calls are
>> explicitly declared in such a manner on MSDN because they are *rare,
>> special-purpose exceptions to an obvious general rule that APIs on
>> multitasking systems must be thread-safe*.
>>
> Where can I find a clear statement in the MS documentation about what in
> the API is, and isn't, thread safe?

That's easy. It's thread-safe if M$ doesn't say otherwise. It's taken as
given that the APIs on a multiThreaded OS are thread-safe. That's not to
say, as I posted before, that some operations cannot be misused for
example: VCL components and Windows forms should only be manipulated from
the thread that created them. One could seriously extrapolate this to 'the
APIs for Windows are not thread-safe', but that is stretching reality beyond
breaking point.

Rgds,
Martin

Marc Rohloff [TeamB]

unread,
Jul 4, 2008, 8:48:34 AM7/4/08
to
On Thu, 3 Jul 2008 15:18:57 -0700, Remy Lebeau (TeamB) wrote:

> For 32-bit CPUs, does the variable exist at a memory address that is evenly
> divisible by 4?

So for a 64-bit CPU would the fields have to be aligned on 8 byte
boundaries? This would mean that a program that does this, and is
compiled, for a 32-bit architecture would not be thread safe on a
64-bit processor.

--
Marc Rohloff [TeamB]
marc -at- marc rohloff -dot- com

Marc Rohloff [TeamB]

unread,
Jul 4, 2008, 8:50:27 AM7/4/08
to
On Thu, 3 Jul 2008 14:41:59 +0100, Enquiring Mind wrote:

> What I thought might not be thread-safe is to call ReadFile in one thread
> and WriteFile in another on the same file.

It also depends on how you define thread safe. AFAIK, Windows will
ensure that all the file descriptors, etc are not corrupted, but if
you have two threads writing to a single file then the contents of the
file are undefined.

Enquiring Mind

unread,
Jul 4, 2008, 12:05:03 PM7/4/08
to

"Martin James" <nos...@tuthill.com> wrote in message
news:486dab44$1...@newsgroups.borland.com...

>
> That's easy. It's thread-safe if M$ doesn't say otherwise. It's taken as
> given that the APIs on a multiThreaded OS are thread-safe. That's not to
> say, as I posted before, that some operations cannot be misused for
> example: VCL components and Windows forms should only be manipulated from
> the thread that created them. One could seriously extrapolate this to
> 'the APIs for Windows are not thread-safe', but that is stretching reality
> beyond breaking point.
>

Most reassuring summary, thanks! I shall now remove the defensive Critical
sections that I wrapped around my calls of API functions featuring a file
handle as an argument, and revert back to how the code was before.

Regards,

EM


0 new messages