Skip to content
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

Native TLS support for pthreads #53995

Closed
kristjanvalur mannequin opened this issue Sep 7, 2010 · 19 comments
Closed

Native TLS support for pthreads #53995

kristjanvalur mannequin opened this issue Sep 7, 2010 · 19 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage

Comments

@kristjanvalur
Copy link
Mannequin

kristjanvalur mannequin commented Sep 7, 2010

BPO 9786
Nosy @loewis, @amauryfa, @pitrou, @kristjanvalur, @giampaolo
Dependencies
  • bpo-9797: wrong assumption in pystate.c
  • Files
  • pthread_tls.patch
  • pthread_tls.patch
  • pthread_tls.patch
  • pthread_tls.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2010-09-20.02:12:18.192>
    created_at = <Date 2010-09-07.05:28:55.092>
    labels = ['interpreter-core', 'performance']
    title = 'Native TLS support for pthreads'
    updated_at = <Date 2010-09-20.02:12:18.191>
    user = 'https://github.com/kristjanvalur'

    bugs.python.org fields:

    activity = <Date 2010-09-20.02:12:18.191>
    actor = 'kristjan.jonsson'
    assignee = 'none'
    closed = True
    closed_date = <Date 2010-09-20.02:12:18.192>
    closer = 'kristjan.jonsson'
    components = ['Interpreter Core']
    creation = <Date 2010-09-07.05:28:55.092>
    creator = 'kristjan.jonsson'
    dependencies = ['9797']
    files = ['18781', '18864', '18868', '18906']
    hgrepos = []
    issue_num = 9786
    keywords = ['patch', 'needs review']
    message_count = 19.0
    messages = ['115742', '115748', '115760', '115836', '115849', '115851', '115859', '115877', '116179', '116272', '116275', '116284', '116288', '116292', '116309', '116345', '116646', '116868', '116905']
    nosy_count = 5.0
    nosy_names = ['loewis', 'amaury.forgeotdarc', 'pitrou', 'kristjan.jonsson', 'giampaolo.rodola']
    pr_nums = []
    priority = 'normal'
    resolution = 'accepted'
    stage = None
    status = 'closed'
    superseder = None
    type = 'performance'
    url = 'https://bugs.python.org/issue9786'
    versions = ['Python 3.2']

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 7, 2010

    The following patch adds native TLS implementation for pthreads, avoiding the relatively slow and clunky default tls implemented in thread.c

    @kristjanvalur kristjanvalur mannequin added interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage labels Sep 7, 2010
    @amauryfa
    Copy link
    Member

    amauryfa commented Sep 7, 2010

    The patch looks good.
    Apart from PyGILState_Ensure(), are there other parts of the code that use these functions?

    @pitrou
    Copy link
    Member

    pitrou commented Sep 7, 2010

    Just tried to apply the patch:

    • test_capi now freezes in auto-thread-state
    • test_threading now freezes in test_finalize_runnning_thread

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 8, 2010

    The code may need a little bit of extra work: The pthreads machine that I have to work with is a PS3 :).
    And, despite the documentation not saying, I suspect that pthread_getspecific() actually does mess with "errno", making it necessary to preserve "errno" when calling PyThread_get_key_value(). (The reason for this is documented in thread_nt.h)

    I'll do some tests and let you know.

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 8, 2010

    "errno" is preserved by PyEval_RestoreThread(), so this isn't the issue.
    What you are probably seeing is latent race conditions in the test suite, made apparent by a non-locking TLS implementation. The test suite isn't free from those, see for example bpo-8799

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 8, 2010

    Hm, both the test you mention are using the (non-recursive) lock to synchronize threads. I can't see anything wrong there.

    Could you please try to replace the cod in pthread_getspecific() with this:

    int err = errno
    void *result = pthread_getspecific(key);
    errno = err;
    return result;

    If this fixes those cases, then there is code somewhere that relies on errno being maintained across these calls.

    @pitrou
    Copy link
    Member

    pitrou commented Sep 8, 2010

    The problem turns out to be in pystate.c (my system returns 0 as a valid key number). See issue bpo-9797.

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 8, 2010

    Ah, good to hear.

    @loewis
    Copy link
    Mannequin

    loewis mannequin commented Sep 12, 2010

    The ifdef should go; pthreads always support TLS (since XPG5, 1997).

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 13, 2010

    I left the ifdef in for a quick and easy way to disable this code for those interested, but I'm happy to remove it if it makes for greater synergy.

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 13, 2010

    Added a new patch with #ifdef remvoved, for greater harmony.

    @loewis
    Copy link
    Mannequin

    loewis mannequin commented Sep 13, 2010

    It seems we need to clarify the return value of PyThread_create_key. The patch returns 0 in case of failure, which is clearly wrong as 0 is also a valid key.

    I think it's safe to return -1: TlsAlloc returns TLS_OUT_OF_INDEXES, which is 0xFFFFFFFF, i.e. -1 on a 32-bit system.

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 13, 2010

    I've changed the function as you suggest, although there are in fact no failure detection semantics defined for PyThread_create_key(). See e.g. thread.c:294

    /* Return a new key.  This must be called before any other functions in
     * this family, and callers must arrange to serialize calls to this
     * function.  No violations are detected.
     */
    int
    PyThread_create_key(void)

    @loewis
    Copy link
    Mannequin

    loewis mannequin commented Sep 13, 2010

    Am 13.09.2010 10:00, schrieb Kristján Valur Jónsson:

    Kristján Valur Jónsson <kristjan@ccpgames.com> added the comment:

    I've changed the function as you suggest, although there are in fact no failure detection semantics defined for PyThread_create_key().

    Right. That's why I'm thinking that we should introduce some. TLS
    creation *can* fail, and it is unfortunate that the original
    introduction of this API forgot to consider that. Your patch did
    (de facto) introduce an error return code (originally 0, now -1).
    So it would be good if this was documented, and the NT version adjusted.

    In principle, this is really difficult to get right. AFAICT,
    pthread_key_t doesn't even have to be an integral type, and even
    if it is, it may well become -1. However, we can probably worry
    about this when a system comes along where this implementation
    breaks.

    @pitrou
    Copy link
    Member

    pitrou commented Sep 13, 2010

    Right. That's why I'm thinking that we should introduce some. TLS
    creation *can* fail, and it is unfortunate that the original
    introduction of this API forgot to consider that. Your patch did
    (de facto) introduce an error return code (originally 0, now -1).

    Perhaps we can simply call Py_FatalError() instead? There's not much we
    can do when such a failure occurs anyway.

    @loewis
    Copy link
    Mannequin

    loewis mannequin commented Sep 13, 2010

    Perhaps we can simply call Py_FatalError() instead? There's not much we
    can do when such a failure occurs anyway.

    Sounds fine as well. Python's own usage definitely shouldn't fail. If
    extension modules use this in an aggressive manner, they may actually
    exhaust TLS keys (at least on Windows, where old versions had only
    64 slots). Having the interpreter fail then sounds reasonable.

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 17, 2010

    Ok, here is a patch. key creation returns -1 on error, and the caller can detect this and raise a fatal error.

    @pitrou
    Copy link
    Member

    pitrou commented Sep 19, 2010

    Patch looks good to me.

    @kristjanvalur
    Copy link
    Mannequin Author

    kristjanvalur mannequin commented Sep 20, 2010

    Committed as revision 84914

    @kristjanvalur kristjanvalur mannequin closed this as completed Sep 20, 2010
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants