-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-99113: A Per-Interpreter GIL! #99114
Closed
ericsnowcurrently
wants to merge
318
commits into
python:main
from
ericsnowcurrently:per-interpreter-gil-new
Closed
Changes from 250 commits
Commits
Show all changes
318 commits
Select commit
Hold shift + click to select a range
25fd52a
Revert "Remove unused refcounts in singletons within CPython/Objects"
eduardo-elizondo be86955
Include immortal interned strings
eduardo-elizondo 38a14a9
Regen frozen main
eduardo-elizondo c828369
Properly clean up all immortal interned strings at runtime finalization
eduardo-elizondo ee41af6
Build and test fixes
eduardo-elizondo f835e6d
Temporarily disable single test_embed test
eduardo-elizondo 8573af4
Fix structseq test
eduardo-elizondo ad19ff6
Move nonetype refcount to static refcnt
eduardo-elizondo 66c625f
Remove unneeded reference counts in Cpython/Objects
eduardo-elizondo 1379d50
Mark global instances as static globals
eduardo-elizondo 1c9ee6d
Remove unneeded reference counts in Cpython/Python
eduardo-elizondo 287b57c
Remove unneeded reference counts in gcmodule.c
eduardo-elizondo c736a7c
Cleanup bool and str usage
eduardo-elizondo 60f0760
Merge branch 'main' into immortal-references
eduardo-elizondo 1321ff6
Fix whitespaces
eduardo-elizondo a719b41
Remove static immortal bit in favor of unicode intern state
eduardo-elizondo 9f3ed39
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 8f72afe
Regen frozen
eduardo-elizondo 52d6d78
Fix regrtest
eduardo-elizondo 9fd8a98
Change immortal refcount for PY_SSIZE_T_MAX
eduardo-elizondo 3478467
Introduce saturated adds for increfs
eduardo-elizondo eb5da8c
Add default and msvc intrinsic saturated add
eduardo-elizondo def8da3
Fix msvc saturated add
eduardo-elizondo fe6727e
Fix docs
eduardo-elizondo 38df3ce
Move unicode_is_singleton to Py_DEBUG
eduardo-elizondo 73f6dcd
Skip immortal checks in frame clear
eduardo-elizondo d68efa1
Make code objects immortal
eduardo-elizondo 18cff33
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 168a85c
Refcount fixes
eduardo-elizondo 9ada9fd
Temporarily disable two code tests
eduardo-elizondo 5d3beb9
Disable one more code test
eduardo-elizondo ea342e3
Cleanups
eduardo-elizondo d78a560
Simplify Implementation
eduardo-elizondo 16d59e3
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo f49c13c
Cleanups
eduardo-elizondo 8262e56
More Cleanups
eduardo-elizondo 96c7caa
Regen Frozen
eduardo-elizondo 3493c85
Fix regrtest
eduardo-elizondo 0f38657
Only immortal changes
eduardo-elizondo 401a3c3
Fix C++ compilation issue
eduardo-elizondo 6bd2d94
Fix regen files
eduardo-elizondo 9df1447
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 15f7365
Fix sat add
eduardo-elizondo ea9f01c
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo c39b617
32 bit fixes
eduardo-elizondo 3ae8374
Fix msvc build
eduardo-elizondo ba7cfe1
Add 32 compat
eduardo-elizondo 7a29123
More fixes
eduardo-elizondo 88ede67
Fix inlined refcounts
eduardo-elizondo 34bdf3c
Change refcount strategy for 32bit systems
eduardo-elizondo ab1f6e4
Add guard for saturated add function
eduardo-elizondo c2c228e
Cleanup unneeded port values
eduardo-elizondo 219ebdc
branchless saturated add
eduardo-elizondo cd42e16
Use PY32 bit integers
eduardo-elizondo 99e7549
Cleanups
eduardo-elizondo d7df473
Remove branchless add as it's slower
eduardo-elizondo 00238eb
Immortalize Interned Strings
eduardo-elizondo 9355ca2
Fix structseq test
eduardo-elizondo eedd412
Bring back interned stats
eduardo-elizondo ccf8b61
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo e57910d
Fix msvc ifdef
eduardo-elizondo 6437df7
Only copy lower 32 bits to refcnt
eduardo-elizondo ba75726
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 418b2ff
Merge cleanups
eduardo-elizondo 1468f52
Fixing Test Failures
eduardo-elizondo e30fea4
Addressed static string issue
eduardo-elizondo 5aa8c34
Addressed regrtest failures
eduardo-elizondo d74a4c5
Addressed CI failures
eduardo-elizondo 9be58d4
Addressed CI failures second try
eduardo-elizondo f00f7f8
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 747039d
Remove temporary fixes
eduardo-elizondo 01017e1
Temporary windows fix
eduardo-elizondo 6f0cf32
Remove duplicate immortal initialization
eduardo-elizondo 7997d57
Windows fix
eduardo-elizondo 749680e
Addressed CI failures third try
eduardo-elizondo c71c742
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo bc28cb0
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo c8b694f
Add tp_dealloc suggested changes by steering committee
eduardo-elizondo 6abab4d
Fixed int leak
eduardo-elizondo 1dfe27a
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 7661541
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 59513a7
Cleanup deallocation of immortal objects
eduardo-elizondo 60329b5
Add DeepFreeze types for typle, long, and bytes
eduardo-elizondo a5e29d5
Fix regencode
eduardo-elizondo f88cbb6
Fix stable abi toml
eduardo-elizondo 7efa760
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 8ebb3db
Add DeepFreeze types for float, complex
eduardo-elizondo 2c3d242
Add DeepFreeze types for code and update stable_abi
eduardo-elizondo 5684be7
Remove PyDeepFreezeCode_Type from stable abi
eduardo-elizondo 4529e23
Revert DeepFreeze changes
eduardo-elizondo cfb56b6
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo a748e80
Replace incref memcpy with builtins
eduardo-elizondo 07a09d4
Pass PyInterpreterState to pymalloc_*().
ericsnowcurrently ca75048
Move the object arenas to the interpreter state.
ericsnowcurrently 4ee199b
Drop an errant #define.
ericsnowcurrently 2768fa4
Leave dump_debug_stats in the global state.
ericsnowcurrently bf9425f
Dynamically initialize obmalloc for subinterpreters.
ericsnowcurrently 83e16d5
Move types.next_version_tag to PyInterpreterState for non-core-static…
ericsnowcurrently c9281e4
Add NEXT_GLOBAL_VERSION_TAG.
ericsnowcurrently 95ffcd1
Handle static types correctly in assign_version_tag().
ericsnowcurrently f3b707d
Verify that builtin types have builtin bases.
ericsnowcurrently c32b834
Add an assert.
ericsnowcurrently 6362a36
Do not invalidate the method cache for static builtin types.
ericsnowcurrently d5da34b
Merge branch 'main' into per-interpreter-alloc
ericsnowcurrently 6c3111c
Pass around struct _obmalloc_state* instead of PyInterpeterState*.
ericsnowcurrently 4dc087d
Add _PyInterpreterConfig.use_main_obmalloc.
ericsnowcurrently 1ae33a0
Add a comment about why per-interpreter obmalloc requires multi-phase…
ericsnowcurrently 5b54d63
Add a TODO comment.
ericsnowcurrently 9f4f8f3
Optionally use the main interpreter's obmalloc state.
ericsnowcurrently aa10204
Pass use_main_obmalloc to run_in_subinterp() in test_import.
ericsnowcurrently 69d9a2d
_Py_GetAllocatedBlocks() -> _Py_GetGlobalAllocatedBlocks().
ericsnowcurrently 25378f8
Errors from _Py_NewInterpreterFromConfig() are no longer fatal.
ericsnowcurrently 1c5b109
Chain the exceptions.
ericsnowcurrently f36426b
Swap out the failed tstate.
ericsnowcurrently 54b9f09
Remaining static builtin types must be fixed.
ericsnowcurrently 2358a42
Add PyInterpreterState.sysdict_copy.
ericsnowcurrently b6502e1
Set m_copy to None for sys and builtins.
ericsnowcurrently 678e67b
Add _PyIO_InitTypes().
ericsnowcurrently 69a5829
Fix test_capi.
ericsnowcurrently 3feb408
Avoid allocation for shared exceptions.
ericsnowcurrently 05806fc
Fix the ChannelID tp_name.
ericsnowcurrently b1cd7bb
Merge branch 'main' into per-interpreter-alloc
ericsnowcurrently 4feb2b7
Do not include the total from interpreters sharing with main.
ericsnowcurrently 136ad2f
Add _PyRuntime.obmalloc.interpreter_leaks.
ericsnowcurrently e19bb37
Track leaked blocks across init/fini cycles.
ericsnowcurrently 6c51997
Clean up assumptions around runtime fini.
ericsnowcurrently f0fcaf6
Merge branch 'main' into per-interpreter-alloc
ericsnowcurrently 0ff65ff
Add stubs for when WITH_PYMALLOC isn't defined.
ericsnowcurrently 7db8d4a
Decref the key in the right interpreter in _extensions_cache_set().
ericsnowcurrently 38bee89
Don't test against sys (for now).
ericsnowcurrently 375a8f2
Clean up SubinterpImportTests.
ericsnowcurrently b0a9e11
Ensure we are testing against the right type of extension.
ericsnowcurrently 5e5d5d5
Add a test that uses an isolated interpreter.
ericsnowcurrently 033c86d
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo 520fbc3
Rebase fixes
eduardo-elizondo 90e0016
Debug build fixes
eduardo-elizondo bc726b0
Cleanups in prep for review
eduardo-elizondo 5e0cd08
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo f7fbf01
Correct whatsnew
eduardo-elizondo 92fbf96
More cleanups
eduardo-elizondo 1c390cc
Delete _PyType_FixCacheRefcounts
eduardo-elizondo 25809ce
Fix is_core_module().
ericsnowcurrently 616d3dd
Merge branch 'main' into per-interpreter-alloc
ericsnowcurrently 43a836b
Ignore last_final_leaks.
ericsnowcurrently 1841b55
Fix a typo.
ericsnowcurrently 299527e
Merge branch 'main' into per-interpreter-alloc
ericsnowcurrently 0091e48
Add a note about global state owned by the module.
ericsnowcurrently 9f74f7b
Factor out GLOBAL_MALLOC() and GLOBAL_FREE().
ericsnowcurrently 10c3589
Switch to the raw allocator.
ericsnowcurrently ff727ec
Merge branch 'channels-raw-allocator' into per-interpreter-alloc
ericsnowcurrently 593430b
Use the raw allocator for _PyCrossInterpreterData_InitWithSize().
ericsnowcurrently f5ae710
atexit_callback -> atexit_py_callback.
ericsnowcurrently e6d4776
Add pycore_atexit.h.
ericsnowcurrently c719f02
Add _Py_AtExit().
ericsnowcurrently 47c302d
Add a TODO comment.
ericsnowcurrently aaeaaa6
Move _Py_AtExit() to the public API.
ericsnowcurrently b5396e4
Test a constraint.
ericsnowcurrently 448b48a
Add an atexit callback for _xxinterpchannels.
ericsnowcurrently c86f738
Implement the callback.
ericsnowcurrently 1827feb
Drop the _PyCrossInterpreterData_Clear() call in _xxinterpchannels.
ericsnowcurrently 82b395c
Drop the _PyCrossInterpreterData_Clear() call in _xxsubinterpreters.
ericsnowcurrently df77a64
Merge branch 'atexit-c-callback' into per-interpreter-alloc
ericsnowcurrently 22758a3
Merge branch 'main' into per-interpreter-alloc
ericsnowcurrently 030016a
Addressed First Round of Comments
eduardo-elizondo c4db85a
Add a thread_local macro.
ericsnowcurrently 47a7094
tstate_current -> thread_local.
ericsnowcurrently cf22de1
Add _PyThraedState_GetCurrent().
ericsnowcurrently 093c405
Address comments
eduardo-elizondo d4136d2
Add HAVE_THREAD_LOCAL.
ericsnowcurrently f8c6598
Support the faster approach, if available.
ericsnowcurrently 6c0fdba
Return Py_DEBUG in unicode runtime shutdown
eduardo-elizondo 9496df0
Do not fail if thread_local not supported.
ericsnowcurrently 74b6e7b
Nits
eduardo-elizondo 2c335a3
thread_local -> _Py_thread_local
ericsnowcurrently 4af0ce7
Only define _Py_thread_local for the core runtime.
ericsnowcurrently 3db4007
Fix pystate.c.
ericsnowcurrently d573053
Call _PyThreadState_GET() from _PyRuntimeState_GetThreadState().
ericsnowcurrently feb8ef5
Fix the error message.
ericsnowcurrently 2332a2e
Add a NEWS entry.
ericsnowcurrently ed86e04
Add PyInterpreterState.ceval.gil.
ericsnowcurrently 3885d43
Use PyInterpreterState.ceval.gil.
ericsnowcurrently c45e633
Add _PyInterpreterConfig.own_gil.
ericsnowcurrently a857530
Use PyInterpreterConfig.own_gil.
ericsnowcurrently 04c023e
Actually make the GIL per-interpreter!
ericsnowcurrently a067e4a
Merge branch 'per-interpreter-alloc' into per-interpreter-gil-combined
ericsnowcurrently 554e03a
Merge branch 'tstate_current-as-thread_local' into per-interpreter-gi…
ericsnowcurrently b2f8e8e
Skip blocking tests.
ericsnowcurrently 433d1e3
Use Py_BUILD_CORE to set PyObject_HEAD_INIT as immortal
eduardo-elizondo 069da16
Address Carl's comments
eduardo-elizondo d22a4bf
Use a union to refer to lower 32bits
eduardo-elizondo e04ef7e
Static declarations cleanups
eduardo-elizondo 3b3b142
Only support split refcount in 64bit architectures
eduardo-elizondo ab3f951
Support incref in big-endian machines
eduardo-elizondo 3e55a32
Cleanups and comments
eduardo-elizondo ff69be7
Fix bytes_method compiler error
eduardo-elizondo e6e459c
Merge remote-tracking branch 'upstream/main' into immortal-references
eduardo-elizondo e1e13df
Skip a blocking test.
ericsnowcurrently b659ca8
Fix a test.
ericsnowcurrently 9a0d093
Add an assert.
ericsnowcurrently 21984e4
Add _PyEval_AcquireLock().
ericsnowcurrently e19f50a
Add Py_ALWAYS_INLINE to Py_DECREF, Py_INCREF, and _Py_IsImmortal
eduardo-elizondo 4ae3319
Add _PyThreadState_SwapNoGIL().
ericsnowcurrently 34103b9
Acquire the GIL when not owned.
ericsnowcurrently e5b7aeb
Un-skip tests.
ericsnowcurrently d43bb5f
Fix tabs.
ericsnowcurrently 02b681c
Add a granular lock for _PyRuntime.imports.extensions.
ericsnowcurrently 1755379
Use the lock.
ericsnowcurrently 9a65073
Merge branch 'extensions-lock' into per-interpreter-gil-new
ericsnowcurrently 12dba6f
Merge remote-tracking branch 'eduardo-elizondo/immortal-references' i…
ericsnowcurrently 63790f6
Immortalize tp_dict, tp_bases, and tp_mro for builtin static types.
ericsnowcurrently 0edcfb5
Do the work in _PyStaticType_InitBuiltin().
ericsnowcurrently 9cdb13a
Add _Py_EnsureImmortal() and _Py_ImmortalObjectsFini().
ericsnowcurrently a9a1f63
Fix an assert.
ericsnowcurrently 42c6a9b
Immortalize in _PyStructSequence_InitBuiltinWithFlags().
ericsnowcurrently e1dde48
Recursively immortalize.
ericsnowcurrently 5f8c3e4
Merge branch 'main' into isolate-types-next-version-tag
ericsnowcurrently 0d78c1b
Only use deepfreeze in the main interpreter.
ericsnowcurrently 4e1d627
Merge branch 'main' into per-interpreter-gil-new
ericsnowcurrently 5496238
Merge branch 'main' into per-interpreter-gil-new
ericsnowcurrently fc6b906
Merge branch 'isolate-types-next-version-tag' into per-interpreter-gi…
ericsnowcurrently a93499c
Merge branch 'main' into per-interpreter-gil-new
ericsnowcurrently d1e4cf5
Make __mro__ a getter.
ericsnowcurrently d3db6bf
Add the fields to static_builtin_state.
ericsnowcurrently b5799d8
Isolate tp_bases.
ericsnowcurrently 2e28be5
Isolate tp_mro.
ericsnowcurrently fb7a025
Add a note.
ericsnowcurrently 2822f0d
Isolate tp_dict.
ericsnowcurrently 68f0008
Fix type_get_bases() and type_get_mro().
ericsnowcurrently de2a3c1
Fix _PyStaticType_InitBuiltin() for subinterpreters.
ericsnowcurrently 8bd3b67
Call _PyType_CheckConsistency() after setting the fields.
ericsnowcurrently 071ef3f
Re-run most of type_ready() under each interpreter.
ericsnowcurrently 850059a
Add some comments.
ericsnowcurrently cd1dd10
Drop an old workaround for previously shared objects.
ericsnowcurrently c328b27
Merge branch 'per-interpreter-static-types-fields' into per-interpret…
ericsnowcurrently 2771f4e
Move Py_TPFLAGS_READYING to each interpreter for static builtin types.
ericsnowcurrently b9343f4
Merge branch 'per-interpreter-static-types-fields' into per-interpret…
ericsnowcurrently 7afb005
Add the Py_mod_multiple_interpreters module def slot.
ericsnowcurrently d708985
Add constants for the Py_mod_multiple_interpreters value.
ericsnowcurrently 8cb5a5a
Add a NEWS entry.
ericsnowcurrently b1d9ba4
Drop _Py_EnsureImmortal().
ericsnowcurrently 07c54ef
Merge branch 'main' into per-interpreter-gil-new
ericsnowcurrently 8f9d6a3
Merge branch 'module-def-slot-supports-interpreters' into per-interpr…
ericsnowcurrently 9c8f1fd
Add Py_MOD_PER_INTERPRETER_GIL_SUPPORTED.
ericsnowcurrently 340a469
Fix the flags.
ericsnowcurrently fcd539a
Merge branch 'module-def-slot-supports-interpreters' into per-interpr…
ericsnowcurrently 6e875bc
Fix the flags.
ericsnowcurrently b1c928f
Merge branch 'module-def-slot-supports-interpreters' into per-interpr…
ericsnowcurrently 31eb898
Fix all the modules.
ericsnowcurrently b3af284
Fix Python-ast.c.
ericsnowcurrently f3fd844
Fix PyModule_FromDefAndSpec2().
ericsnowcurrently File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
Misc/NEWS.d/next/Core and Builtins/2023-05-03-17-46-47.gh-issue-104108.GOxAYt.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Multi-phase init extension modules may now indicate whether or not they | ||
actually support multiple interpreters. By default such modules are | ||
expected to support use in multiple interpreters. In the uncommon case that | ||
one does not, it may use the new ``Py_mod_multiple_interpreters`` module def | ||
slot. A value of ``0`` means the module does not support them. ``1`` means | ||
it does. The default is ``1``. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We certainly need to use Argument Clinic here (edit: not in this PR, otherwise the diff will become hard to read. Probably not in 3.12b1 either).