Commit Graph

65 Commits

Author SHA1 Message Date
Konrad `ktoso` Malawski
703595e396 [Concurrent] Warnings/errors should use "sendable" not "concurrent"
Resolves rdar://83416205
2021-09-23 12:45:07 +09:00
Kuba (Brecka) Mracek
aaff37ffb8 Add a SWIFT_STDLIB_HAS_DARWIN_LIBMALLOC flag to allow/disallow uses of Darwin libmalloc APIs (malloc_default_zone, malloc_zone_malloc, etc.) (#33812) 2021-08-23 19:37:43 -07:00
David Zarzycki
54e20177c5 [runtime] Fix use-after-free bug 2021-05-01 12:24:02 -04:00
Mike Ash
70354af2b5 [Runtime] Avoid operator new/delete in ConcurrentReadableArray.
The callbacks made in ImageInspectionMachO.cpp are called in a dangerous context, with the dyld and ObjC runtime locks held. C++ allows programs to overload the global operator new/delete, and there's no guarantee that those overloads behave. Ideally, we'd avoid them entirely, but that's a bigger job. For now, avoid the worst trouble by avoiding STL and new/delete in these callbacks. That use came from ConcurrentReadableArray's free list, so we switch that from a std::vector to a linked list.

rdar://75036800
2021-04-09 09:29:20 -04:00
Mike Ash
1557dbcb86 [Runtime] Make Concurrent.h ReaderCount loads seq_cst as well since they need to be ordered with the emplacement of new storage pointers. 2021-01-12 16:46:08 -05:00
Mike Ash
ef8d20a0e6 [Runtime] Fix incorrect memory ordering in ConcurrentReadableArray/HashMap.
When reallocating storage, the storing the pointer to the new storage had insufficiently strong ordering. This could cause writers to check the reader count before storing the new storage pointer. If a reader then came in between that load and store, it would end up using the old storage pointer, while the writer could end up freeing it.

Also adjust the Concurrent.cpp tests to test with a variety of reader and writer counts. Counterintuitively, when freeing garbage is gated on there being zero readers, having a single reader will shake out problems that having lots of readers will not. We were testing with lots of readers in order to stress the code as much as possible, but this resulted in it being extremely rare for writers to ever see zero active readers.

rdar://69798617
2021-01-12 10:41:56 -05:00
Mike Ash
13f84ddd7e [Runtime] Fix premature snapshot destruction in StableAddressConcurrentReadableHashMap::find.
Mark the relevant snapshot methods as ref-qualified (adding a & after the parameter list) so the compiler will enforce this for us and forbid calling them on temporaries.

rdar://72997638
2021-01-11 10:59:08 -05:00
Mike Ash
4ccfdfb72a [Runtime] Fix StableAddressConcurrentReadableHashMap threading crash.
StableAddressConcurrentReadableHashMap::getOrInsert had a race condition in the first lookup, where the snapshot was destroyed before the pointer was extracted from the returned wrapper. Fix this by creating the snapshot outside the if so that it stays alive.

rdar://problem/71932487
2020-12-21 16:52:56 -05:00
Mike Ash
768a085de8 Merge pull request #34598 from mikeash/os-unfair-lock-mutex
[Runtime] Use os_unfair_lock for Mutex and StaticMutex on Darwin.
2020-11-11 11:37:12 -05:00
Mike Ash
1b376cddf1 Merge pull request #34463 from mikeash/concurrentreadablehashmap-inline-indices
[Runtime] Have ConcurrentReadableHashMap store indices inline when the table is sufficiently small.
2020-11-10 14:59:16 -05:00
Mike Ash
e82d9e8c7b Move ConditionMutex to ConditionVariable::Mutex and move various other Mutex.h types to be nested. 2020-11-10 14:44:59 -05:00
Mike Ash
12d114713f [Runtime] Switch MetadataCache to ConcurrentReadableHashMap. (#34307)
* [Runtime] Switch MetadataCache to ConcurrentReadableHashMap.

Use StableAddressConcurrentReadableHashMap. MetadataCacheEntry's methods for awaiting a particular state assume a stable address, where it will repeatedly examine `this` in a loop while waiting on a condition variable, so we give it a stable address to accommodate that. Some of these caches may be able to tolerate unstable addresses if this code is changed to perform the necessary table lookup each time through the loop instead. Some of them store metadata inline and we assume metadata never moves, so they'll have to stay this way.

* Have StableAddressConcurrentReadableHashMap remember the last found entry and check that before doing a more expensive lookup.

* Make a SmallMutex type that stores the mutex data out of line, and use it to get LockingConcurrentMapStorage to fit into the available space on 32-bit.

rdar://problem/70220660
2020-11-04 15:10:50 -05:00
Mike Ash
782fa27206 [Runtime] Move ElementCapacity into the Elements allocation.
This shrinks ConcurrentReadableHashMap a bit, which will be needed for adapting it for metadata caches.
2020-10-28 10:23:21 -04:00
Mike Ash
9f53d4a52e [Runtime] Have ConcurrentReadableHashMap store indices inline when the table is sufficiently small. 2020-10-27 11:55:31 -04:00
Mike Ash
630aff7b19 [Runtime] Change SimpleGlobalCache to use ConcurrentReadableHashMap instead of ConcurrentMap.
This gives us faster lookups and a small advantage in memory usage. Most of these maps need stable addresses for their entries, so we add a level of indirection to ConcurrentReadableHashMap for these cases to accommodate that. This costs some extra memory, but it's still a net win.

A new StableAddressConcurrentReadableHashMap type handles this indirection and adds a convenience getOrInsert to take advantage of it.

ConcurrentReadableHashMap is tweaked to avoid any global constructors or destructors when using it as a global variable.

ForeignWitnessTables does not need stable addresses and it now uses ConcurrentReadableHashMap directly.

rdar://problem/70056398
2020-10-08 14:57:39 -04:00
Pavel Yaskevich
e6b140e32b [Runtime] NFC: Fix swift_runtime_unreachable to swift_unreachable 2020-10-08 11:54:12 -07:00
Mike Ash
ece0399d60 [Runtime] Have ConcurrentReadableHashMap use 1-byte or 2-byte indices when possible. 2020-09-24 15:28:18 -04:00
Mike Ash
0990fa90b3 Merge pull request #33647 from mikeash/shrink-concurrentreadablehashmap
[Runtime] Shrink ConcurrentReadableHashMap a bit.
2020-08-28 14:45:17 -04:00
Mike Ash
4cd1b715bd [Runtime] Shrink ConcurrentReadableHashMap a bit.
We're using a lot of space on the free lists. Each vector is three words, and we have two of them. Switch to a single linked list. We only need one list, as both kinds of pointers just get free()'d. A linked list optimizes for the common case where the list is empty. This takes us from six words to one.

Also make ReaderCount, ElementCount, and ElementCapacity uint32_ts. The size_ts were unnecessarily large and this saves some space on 64-bit systems.

While we're in there, add 0/NULL initialization to all elements. The current use in the runtime is unaffected (it's statically allocated) but the local variables used in the test were tripping over this.
2020-08-27 13:05:40 -04:00
Mike Ash
58604ff1ba [Runtime] Fix memory ordering on a store in ConcurrentReadableArray. 2020-08-26 13:24:44 -04:00
Mike Ash
6467827add [Runtime] Fix memory ordering on two loads in ConcurrentReadableHashMap. 2020-08-24 15:29:37 -04:00
Mike Ash
af35936589 [Runtime] Fix a race condition in ConcurrentReadableHashMap with concurrent reads and clears. 2020-08-22 10:51:04 -04:00
Mike Ash
ecd6d4ddec Add a new ConcurrentReadableHashMap type. Switch the protocol conformance cache
to use it.

ConcurrentReadableHashMap is lock-free for readers, with writers using a lock to
ensure mutual exclusion amongst each other. The intent is to eventually replace
all uses ConcurrentMap with ConcurrentReadableHashMap.

ConcurrentReadableHashMap provides for relatively quick lookups by using a hash
table. Rearders perform an atomic increment/decrement in order to inform writers
that there are active readers. The design attempts to minimize wasted memory by
storing the actual elements out-of-line, and having the table store indices into
a separate array of elements.

The protocol conformance cache now uses ConcurrentReadableHashMap, which
provides faster lookups and less memory use than the previous ConcurrentMap
implementation. The previous implementation caches
ProtocolConformanceDescriptors and extracts the WitnessTable after the cache
lookup. The new implementation directly caches the WitnessTable, removing an
extra step (potentially a quite slow one) from the fast path.

The previous implementation used a generational scheme to detect when negative
cache entries became obsolete due to new dynamic libraries being loaded, and
update them in place. The new implementation just clears the entire cache when
libraries are loaded, greatly simplifying the code and saving the memory needed
to track the current generation in each negative cache entry. This means we need
to re-cache all requested conformances after loading a dynamic library, but
loading libraries at runtime is rare and slow anyway.

rdar://problem/67268325
2020-08-20 13:05:30 -04:00
Anthony Latsis
9fd1aa5d59 [NFC] Pre- increment and decrement where possible 2020-06-01 15:39:29 +03:00
Saleem Abdulrasool
3fa1d1fe3f runtime: ingest LLVMSupport into the runtime
This adds a new copy of LLVMSupport into the runtime.  This is the final
step before changing the inline namespace for the runtime support.  This
will allow us to avoid the ODR violations from the header definitions of
LLVMSupport.

LLVMSupport forked at: 22492eead218ec91d349c8c50439880fbeacf2b7
Changes made to LLVMSupport from that revision:
  process.inc forward declares `_beginthreadex` due to compilation issues due to custom flag handling

API changes required that we alter the `Deallocate` routine to account
for the alignment.

This is a temporary state, meant to simplify the process.  We do not use
the entire LLVMSupport library and there is no value in keeping the
entire library.  Subsequent commits will prune the library to the needs
for the runtime.
2020-05-15 09:55:36 -07:00
Mike Ash
a4863c4dcd [Runtime] Fix ConcurrentReadableArray's handling of FreeList to not double-free items. Also implement a destructor so it can be used for non-globals.
rdar://problem/40484362
2018-05-23 11:29:26 -04:00
Mike Ash
c7eeeb5a68 [Runtime] Change ConcurrentReadableArray's API to provide iterable snapshots rather than using a callback-based read call.
rdar://problem/40230581
2018-05-23 11:19:42 -04:00
Mike Ash
fdf67e80cc [Runtime] Include <vector> in Concurrent.h, since it uses std::vector.
rdar://problem/37173156
2018-05-16 14:44:49 -04:00
Mike Ash
da4fa67d7e [Runtime] Move ConcurrentReadableArray's allocate/deallocate functions into Storage. Mark ConcurrentReadableArray as un-copyable, un-assignable, and un-movable. Use SWIFT_MEMORY_ORDER_CONSUME instead of std::memory_order_consume. Make read() pass a const pointer.
rdar://problem/37173156
2018-05-15 15:27:33 -04:00
Mike Ash
68adaebf52 [Runtime] Properly set the count in newly allocated storage in ConcurrentReadableArray. Remove a redundant load of Count. Fix memory ordering on ReaderCount.
rdar://problem/37173156
2018-05-09 15:31:53 -04:00
Mike Ash
2a0c4bf368 [Runtime] Clean up and lightly document ConcurrentReadableArray. Check for malloc failure. Use placement new when appending values.
rdar://problem/37173156
2018-05-01 12:52:58 -04:00
Mike Ash
8b59295a92 [Runtime] Change protocol conformance scanning to use a concurrent array rather than a locked vector.
rdar://problem/37173156
2018-04-30 12:24:47 -04:00
John McCall
f304c321f3 Rewrite MetadataCache to be a more natural extension of ConcurrentMap.
Change generic witness table instantiation to use a more lightweight
entry scheme that allocates the witness table as part of the entry.

In contrast, change generic metadata instantiation to use a more
straightforward allocation scheme where the metadata is a totally
independent allocation.

This is preparation for proper cyclic-dependency handling.
2018-03-08 02:29:20 -05:00
Calvin Hill
aee81d272f Add Initial platform support for Haiku. (#11583) 2017-09-22 21:06:56 -04:00
John McCall
038303b1b1 Switch MetadataCache to use a global slab allocator.
This seems to more than fix a performance regression that we
detected on a metadata-allocation microbenchmark.

A few months ago, I improved the metadata cache representation
and changed the metadata allocation scheme to primarily use malloc.
Previously, we'd been using malloc in the concurrent tree data
structure but a per-cache slab allocator for the metadata itself.
At the time, I was concerned about the overhead of per-cache
allocators, since many metadata patterns see only a small number
of instantiations.  That's still an important factor, so in the
new scheme we're using a global allocator; but instead of using
malloc for individual allocations, we're using a slab allocator,
which should have better peak, single-thread performance, at the
cost of not easily supporting deallocation.  Deallocation is
only used for metadata when there's contention on the cache, and
specifically only when there's contention for the same key, so
leaking a little isn't the worst thing in the world.

The initial slab is a 64K globally-allocated buffer.
Successive slabs are 16K and allocated with malloc.

rdar://28189496
2017-02-14 11:10:44 -05:00
Hugh Bellamy
d457742a8d Change getKeyIntValueForDump to use intptr_t rather than long 2017-02-12 09:46:36 +07:00
John McCall
2b25701a93 Revert "Switch MetadataCache to use a global slab allocator."
This reverts commit ccbe5fcf73.
2017-01-29 00:17:30 -05:00
John McCall
ccbe5fcf73 Switch MetadataCache to use a global slab allocator.
This seems to more than fix a performance regression that we
detected on a metadata-allocation microbenchmark.

A few months ago, I improved the metadata cache representation
and changed the metadata allocation scheme to primarily use malloc.
Previously, we'd been using malloc in the concurrent tree data
structure but a per-cache slab allocator for the metadata itself.
At the time, I was concerned about the overhead of per-cache
allocators, since many metadata patterns see only a small number
of instantiations.  That's still an important factor, so in the
new scheme we're using a global allocator; but instead of using
malloc for individual allocations, we're using a slab allocator,
which should have better peak, single-thread performance, at the
cost of not easily supporting deallocation.  Deallocation is
only used for metadata when there's contention on the cache, and
specifically only when there's contention for the same key, so
leaking a little isn't the worst thing in the world.

The initial slab is a 64K globally-allocated buffer.
Successive slabs are 16K and allocated with malloc.

rdar://28189496
2017-01-28 02:37:22 -05:00
Han Sangjin
b8dd577693 [swiftc] Fixed for Cygwin
Fixed for the difference of Cygwin with other Windows variants (MSVC,
Itanium, MinGW).

- The platform name is renamed to "cygwin" from "windows" which is used
  for searching the standard libraries.

- The consideration for DLL storage class (DllExport/DllImport) is not
  required for Cygwin and MinGW. There is no problem when linking in
  these environment.

- Cygwin should use large memory model as default.(This may be changed
  if someone ports to 32bit)

- Cygwin and MinGW should use the autolink feature in the sameway of
  Linux due to the linker's limit.
2017-01-19 05:48:24 +09:00
practicalswift
6d1ae2a39c [gardening] 2016 → 2017 2017-01-06 16:41:22 +01:00
practicalswift
797b80765f [gardening] Use the correct base URL (https://swift.org) in references to the Swift website
Remove all references to the old non-TLS enabled base URL (http://swift.org)
2016-11-20 17:36:03 +01:00
John McCall
81b27c210b Permit ConcurrentMap to be templated over an allocator and move
MetadataCache's allocator into it.

The major functional change here is that MetadataCache will now use
the slab allocator for tree nodes, but I also switched the Hashable
conformances cache to use ConcurrentMap directly instead of a
Lazy<ConcurrentMap<>>.
2016-09-01 14:09:43 -07:00
John McCall
17d72f558b Simplify and optimize the structural type metadata caches to use ConcurrentMap directly.
Previously, these were all using MetadataCache.  MetadataCache is a
more heavyweight structure which acquires a lock before building the
metadata.  This is appropriate if building the metadata is very
expensive or might have semantic side-effects which cannot be rolled
back.  It's also useful when there's a risk of re-entrance, since it
can diagnose such things instead of simply dead-locking or infinitely
recursing.  However, it's necessary for structural cases like tuple
and function types, and instead we can just use ConcurrentMap, which
does a compare-and-swap to publish the constructed metadata and
potentially destroys it if another thread successfully won the race.

This is an optimization which we could not previously attempt.

As part of this, fix tuple metadata uniquing to consider the label
string correctly.  This exposes a bug where the runtime demangling
of tuple metadata nodes doesn't preserve labels; fix this as well.
2016-08-31 18:53:54 -07:00
Greg Parker
e0656515b9 Revert "Metadata cache optimizations" 2016-08-29 19:03:40 -07:00
John McCall
b7bd752946 Simplify and optimize the structural type metadata caches to use ConcurrentMap directly.
Previously, these were all using MetadataCache.  MetadataCache is a
more heavyweight structure which acquires a lock before building the
metadata.  This is appropriate if building the metadata is very
expensive or might have semantic side-effects which cannot be rolled
back.  It's also useful when there's a risk of re-entrance, since it
can diagnose such things instead of simply dead-locking or infinitely
recursing.  However, it's necessary for structural cases like tuple
and function types, and instead we can just use ConcurrentMap, which
does a compare-and-swap to publish the constructed metadata and
potentially destroys it if another thread successfully won the race.

This is an optimization which we could not previously attempt.

As part of this, fix tuple metadata uniquing to consider the label
string correctly.  This exposes a bug where the runtime demangling
of tuple metadata nodes doesn't preserve labels; fix this as well.
2016-08-25 22:27:17 -07:00
Anna Zaks
5320deff66 Tweak the memory ordering in ConcurrentMap
Make sure the memory synchronization ordering on success is strictly stronger than the memory ordering of failure. This addresses a race reported by TSan when having both Swift tests and the runtime TSanified.
2016-04-06 11:54:07 -07:00
Davide Italiano
59ed25c208 [FreeBSD] Include <stdio.h>, needed for printf(). 2016-02-29 19:40:22 +00:00
John McCall
fc261045a5 Optimize the number of accesses performed on ConcurrentMap
and MetadataCache and fix a re-entrancy bug in metadata
instantiation.

The re-entrancy bug is that we were holding the instantiation
lock of a metadata cache while instantiating metadata.  Doing
so prevents us from creating a different instantiation if
it's needed by the outer instantiation.  This is already
possible, but it's much more likely in a patch I'm working on
to only store the minimal metadata for generic parameters
in generic types.

The same bug could also show up as a deadlock between threads,
so a recursive lock would not be a good fix.  Instead, we add
a condition variable to the metadata cache.  When fetching
metadata, we look for a node in the concurrent map, eagerly
creating an empty one if none currently exists.  If lookup
finds an empty node, we wait on the condition variable for
the node to become populated.  If lookup succeeds in creating
an empty node, we instantiate the metadata, grab the lock,
populate the node, and notify the condition variable.

Safely creating an empty node without any metadata present
requires us to move the key data into the map entry.  That,
plus a few other invariant shifts, makes it sensible to
give the user of ConcurrentMap more control over the
allocation of map nodes and the layout of keys.  That, in
turn, allows us to change the contract so that keys can be
more complex than just a hash code.  Instead of incrementing
hash codes and re-performing the lookup, we just insist
that lookup keys be totally ordered.

For now, I've kept the uniform use of hash codes as a
component of the key for MetadataCaches.  However, hash
codes aren't really profitable for small keys, and we should
probably use direct comparisons instead.

We should also switch the safer metadata caches (i.e. the
ones that don't involve calling an arbitrary instantiation
function, like MetatypeMetadataCache) over to directly use
ConcurrentMap.

LLDB's requirement that we maintain a linked list of metadata
cache instantiations with a known layout means we can't yet
remove the CacheEntry's redundant copy of the generic
arguments.
2016-02-25 01:11:57 -08:00
Nadav Rotem
866b44cbae [Debug] Add add a method to dump dotty style graph.
Add add a method to dump the metadata caches as a dotty graph.
2016-02-09 23:14:27 -08:00
practicalswift
2e8190016d [gardening] Fix recently introduced typo: "collissions" → "collisions" 2016-02-09 22:46:29 +01:00