public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin@cygwin.com
Subject: Re: [ANNOUNCEMENT] python3 3.6.1-2 (x86 only)
Date: Tue, 28 Mar 2017 12:38:00 -0000	[thread overview]
Message-ID: <20170328205231.e62a862e4e350b9b1f773de8@nifty.ne.jp> (raw)
In-Reply-To: <20170325094638.5209c67a5efef02f51a99e75@nifty.ne.jp>

[-- Attachment #1: Type: text/plain, Size: 1664 bytes --]

On Sat, 25 Mar 2017 09:46:38 +0900 Takashi Yano wrote:
> from ctypes import pythonapi
> key = pythonapi.PyThread_create_key()
> res1 = pythonapi.PyThread_set_key_value(key, 5555)
> res2 = pythonapi.PyThread_get_key_value(key)
> res3 = pythonapi.PyThread_delete_key(key)
> print(key,res1,res2,res3)

There was one mistake. The function type of PyThread_delete_key() is
void, so the return value is meaningless (just a garbage).

Moreover, the script works as expected if modified as follows.

--- from here ---
from ctypes import *
pythonapi.PyThread_create_key.restype = c_long
pythonapi.PyThread_set_key_value.argtypes = [c_long, c_void_p]
pythonapi.PyThread_get_key_value.restype = c_void_p
pythonapi.PyThread_get_key_value.argtypes = [c_long]
key = pythonapi.PyThread_create_key()
res1 = pythonapi.PyThread_set_key_value(key, 5555)
res2 = pythonapi.PyThread_get_key_value(key)
print(key,res1,res2)
--- to here ---

This is because 3.6-thread-cygwin64.patch is changing the type of
functions as the key type is changed from int to long.

However, from the portability point of view, it is not desirable to
change the types of functions exported as APIs.

If one of the idea of the patches I proposed will be employed, the
patch 3.6-thread-cygwin64.patch is not necessary anymore.

Thus, I would like to propose new version of the patches replacing
3.6-thread-cygwin64.patch.

3.6-thread-cygwin-replacement-1.patch:
  replaces 3.6-thread-cygwin64.patch and pthread-cygwin-1.patch

3.6-thread-cygwin-replacement-2.patch:
  replaces 3.6-thread-cygwin64.patch and pthread-cygwin-2.patch

I would appreciate your comment.

-- 
Takashi Yano <takashi.yano@nifty.ne.jp>

[-- Attachment #2: 3.6-thread-cygwin-replacement-1.patch --]
[-- Type: application/octet-stream, Size: 1906 bytes --]

--- origsrc/Python-3.6.1/Python/thread_pthread.h	2017-03-25 08:10:30.784601800 +0900
+++ src/Python-3.6.1/Python/thread_pthread.h	2017-03-25 08:43:12.070906900 +0900
@@ -603,6 +603,64 @@
 
 #define Py_HAVE_NATIVE_TLS
 
+#ifdef __CYGWIN__
+/* Cygwin pthread TLS key type is a pointer, whereas Python 3 assumes
+ * int type. So wrapper functions are used instead.
+ */
+static unsigned long keybase = ULONG_MAX;
+
+static int
+py_pthread_key_create(unsigned int *key, void(*func)(void *))
+{
+    int ret;
+    const unsigned long mask = ULONG_MAX & ~(unsigned long)INT_MAX;
+    unsigned long keybase_new;
+    pthread_key_t key_cyg;
+    ret = pthread_key_create(&key_cyg, func);
+    if (ret) {
+        /* Error */
+        return ret;
+    }
+    keybase_new = (unsigned long)key_cyg & mask;
+    /* If base address is different, treat as error */
+    if (keybase != ULONG_MAX && keybase_new != keybase) {
+        pthread_key_delete(key_cyg);
+        return ENOMEM;
+    }
+    keybase = keybase_new;
+    *key = (unsigned int)((unsigned long)key_cyg & ~mask);
+    return 0;
+}
+
+static int
+py_pthread_key_delete(unsigned int key)
+{
+    pthread_key_t key_cyg = (pthread_key_t)(keybase | key);
+    return pthread_key_delete(key_cyg);
+}
+
+static int
+py_pthread_setspecific(unsigned int key, const void *p)
+{
+    pthread_key_t key_cyg = (pthread_key_t)(keybase | key);
+    return pthread_setspecific(key_cyg, p);
+}
+
+static void *
+py_pthread_getspecific(unsigned int key)
+{
+    pthread_key_t key_cyg = (pthread_key_t)(keybase | key);
+    return pthread_getspecific(key_cyg);
+}
+
+#define pthread_key_t unsigned int
+#define pthread_key_create py_pthread_key_create
+#define pthread_key_delete py_pthread_key_delete
+#define pthread_setspecific py_pthread_setspecific
+#define pthread_getspecific py_pthread_getspecific
+
+#endif /* __CYGWIN__ */
+
 int
 PyThread_create_key(void)
 {


[-- Attachment #3: 3.6-thread-cygwin-replacement-2.patch --]
[-- Type: application/octet-stream, Size: 1940 bytes --]

--- origsrc/Python-3.6.1/Python/thread_pthread.h	2017-03-25 08:10:30.784601800 +0900
+++ src/Python-3.6.1/Python/thread_pthread.h	2017-03-25 08:44:21.946596600 +0900
@@ -603,6 +603,74 @@
 
 #define Py_HAVE_NATIVE_TLS
 
+#ifdef __CYGWIN__
+/* Cygwin pthread TLS key type is a pointer, whereas Python 3 assumes
+ * int type. So wrapper functions are used instead.
+ */
+static pthread_key_t key_tbl[PTHREAD_KEYS_MAX];
+
+static int
+py_pthread_key_create(unsigned int *key, void(*func)(void *))
+{
+    int ret;
+    int i;
+    pthread_key_t key_cyg;
+    ret = pthread_key_create(&key_cyg, func);
+    if (ret) {
+        /* Error */
+        return ret;
+    }
+    for (i=0; i<PTHREAD_KEYS_MAX; i++) {
+        if (key_tbl[i] == NULL) {
+            /* Succeeded */
+            key_tbl[i] = key_cyg;
+            *key = i;
+            return 0;
+        }
+    }
+    pthread_key_delete(key_cyg);
+    /* PTHREAD_KEYS_MAX reached */
+    return EAGAIN;
+}
+
+static int
+py_pthread_key_delete(unsigned int key)
+{
+    int ret;
+    if (key >= PTHREAD_KEYS_MAX || key_tbl[key] == NULL) {
+        return EINVAL;
+    }
+    ret = pthread_key_delete(key_tbl[key]);
+    key_tbl[key] = NULL;
+    return ret;
+}
+
+static int
+py_pthread_setspecific(unsigned int key, const void *p)
+{
+    if (key >= PTHREAD_KEYS_MAX || key_tbl[key] == NULL) {
+        return EINVAL;
+    }
+    return pthread_setspecific(key_tbl[key], p);
+}
+
+static void *
+py_pthread_getspecific(unsigned int key)
+{
+    if (key >= PTHREAD_KEYS_MAX || key_tbl[key] == NULL) {
+        return NULL;
+    }
+    return pthread_getspecific(key_tbl[key]);
+}
+
+#define pthread_key_t unsigned int
+#define pthread_key_create py_pthread_key_create
+#define pthread_key_delete py_pthread_key_delete
+#define pthread_setspecific py_pthread_setspecific
+#define pthread_getspecific py_pthread_getspecific
+
+#endif /* __CYGWIN__ */
+
 int
 PyThread_create_key(void)
 {


[-- Attachment #4: Type: text/plain, Size: 219 bytes --]


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

  reply	other threads:[~2017-03-28 11:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20170324182610.8B2F9440070@conbox-039.nifty.com>
2017-03-25  6:10 ` Takashi Yano
2017-03-28 12:38   ` Takashi Yano [this message]
2017-03-24 19:58 Yaakov Selkowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170328205231.e62a862e4e350b9b1f773de8@nifty.ne.jp \
    --to=takashi.yano@nifty.ne.jp \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).