From: "Marc Nieper-Wißkirchen" <marc@nieper-wisskirchen.de>
To: "David Malcolm" <dmalcolm@redhat.com>,
"Marc Nieper-Wißkirchen" <marc.nieper+gnu@gmail.com>,
jit@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH][jit] Add thread-local globals to the libgccjit frontend
Date: Tue, 01 Jan 2019 00:00:00 -0000 [thread overview]
Message-ID: <f81e88af-671d-9ad8-240f-0537684083f8@nieper-wisskirchen.de> (raw)
In-Reply-To: <1546968499.7788.80.camel@redhat.com>
[...]
>> 2019-01-08 Marc Nieper-WiÃkirchen <marc@nieper-wisskirchen.de>
>>
>> * docs/topics/compatibility.rst: Add LIBGCCJIT_ABI_11.
>> * docs/topics/expressions.rst (Global variables): Add
>> documentation of gcc_jit_lvalue_set_bool_thread_local.
>> * docs/_build/texinfo/libgccjit.texi: Regenerate.
>> * jit-playback.c: Include "varasm.h".
>> Within namespace gcc::jit::playback...
>> (context::new_global) Add "thread_local_p" param and use it
>> to set DECL_TLS_MODEL.
>> * jit-playback.h: Within namespace gcc::jit::playback...
>> (context::new_global): Add "thread_local_p" param.
>> * jit-recording.c: Within namespace gcc::jit::recording...
>> (global::replay_into): Provide m_thread_local to call to
>> new_global.
>> (global::write_reproducer): Call write_reproducer_thread_local.
>> (global::write_reproducer_thread_local): New method.
>> * jit-recording.h: Within namespace gcc::jit::recording...
>> (lvalue::dyn_cast_global): New virtual function.
>> (global::m_thread_local): New field.
>> * libgccjit.c (gcc_jit_lvalue_set_bool_thread_local): New
>> function.
>> * libgccjit.h
>> (LIBGCCJIT_HAVE_gcc_jit_lvalue_set_bool_thread_local): New
>> macro.
>> (gcc_jit_lvalue_set_bool_thread_local): New function.
>> * libgccjit.map (LIBGCCJIT_ABI_11): New.
>> (gcc_jit_lvalue_set_bool_thread_local): Add.
>> * ../testsuite/jit.dg/all-non-failing-tests.h: Include new
>> test.
>> * ../testsuite/jit.dg/jit.exp: Load pthread for tests involving
>> thread-local globals.
>> * ../testsuite/jit.dg/test-thread-local.c: New test case for
>> thread-local globals.
>
> BTW, the convention here is to split out the ChangeLog entries by
> directory based on the presence of ChangeLog files.
>
> There's a gcc/jit/ChangeLog and a gcc/testsuite/ChangeLog, so for this
> patch there should be two sets of ChangeLog entries, one for each of
> these, with the paths expressed relative to the directory holding the
> ChangeLog.
>
> So the testsuite entries would go into gcc/testsuite/ChangeLog, and
> look like:
>
> * jit.dg/all-non-failing-tests.h: Include new test.
>
> ...etc.
>
Thanks for explaining the policy. Corrected ChangeLogs:
gcc/jit/ChangeLog
=================
2019-01-08 Marc Nieper-WiÃkirchen <marc@nieper-wisskirchen.de>
* docs/topics/compatibility.rst: Add LIBGCCJIT_ABI_11.
* docs/topics/expressions.rst (Global variables): Add
documentation of gcc_jit_lvalue_set_bool_thread_local.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* jit-playback.c: Include "varasm.h".
Within namespace gcc::jit::playback...
(context::new_global) Add "thread_local_p" param and use it
to set DECL_TLS_MODEL.
* jit-playback.h: Within namespace gcc::jit::playback...
(context::new_global): Add "thread_local_p" param.
* jit-recording.c: Within namespace gcc::jit::recording...
(global::replay_into): Provide m_thread_local to call to
new_global.
(global::write_reproducer): Call write_reproducer_thread_local.
(global::write_reproducer_thread_local): New method.
* jit-recording.h: Within namespace gcc::jit::recording...
(lvalue::dyn_cast_global): New virtual function.
(global::m_thread_local): New field.
* libgccjit.c (gcc_jit_lvalue_set_bool_thread_local): New
function.
* libgccjit.h
(LIBGCCJIT_HAVE_gcc_jit_lvalue_set_bool_thread_local): New
macro.
(gcc_jit_lvalue_set_bool_thread_local): New function.
* libgccjit.map (LIBGCCJIT_ABI_11): New.
(gcc_jit_lvalue_set_bool_thread_local): Add.
gcc/testsuite/ChangeLog
=======================
2019-01-08 Marc Nieper-WiÃkirchen <marc@nieper-wisskirchen.de>
* jit.dg/all-non-failing-tests.h: Include new test.
* jit.dg/jit.exp: Load pthread for tests involving
thread-local globals.
* jit.dg/test-thread-local.c: New test case for
thread-local globals.
[...]
>> diff --git a/gcc/testsuite/jit.dg/test-thread-local.c
>> b/gcc/testsuite/jit.dg/test-thread-local.c
>> new file mode 100644
>> index 000000000..287ba85e4
>> --- /dev/null
>> +++ b/gcc/testsuite/jit.dg/test-thread-local.c
>> @@ -0,0 +1,99 @@
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <pthread.h>
>> +
>> +#include "libgccjit.h"
>> +
>> +#include "harness.h"
>> +
>> +void
>> +create_code (gcc_jit_context *ctxt, void *user_data)
>> +{
>> + /* Let's try to inject the equivalent of:
>> +
>> + static thread_local int tl;
>> + set_tl (int v)
>> + {
>> + tl = v;
>> + }
>> +
>> + int
>> + get_tl (void)
>> + {
>> + return tl;
>> + }
>
> Thanks for posting this.
>
> This test is OK as far as it goes, but there are some gaps in test
> coverage: the test verifies that jit-generated code can create a new
> thread-local variable, and writes to it, but it doesn't seem to test
> reading from it; e.g. there doesn't seem to be a CHECK_VALUE that the
> thread-local var is 43 after the set_tl (43);
The test does check reading the thread-local variable in the main
thread. If the variable were non thread-local, the value 42 set in the
main thread would have been overwritten by the subordinate thread.
>
> It would probably also be good to verify that jit-generated code can
> work with a thread-local variable declared and defined in C-generated
> code.
>
> Thinking aloud, how about the following changes:
> - split out the thread-local vars there's e.g. a
> extern thread_local int tl_c;
> in the C code and the "tl" becomes "tl_jit", and access it via a
> GCC_JIT_GLOBAL_EXTERNAL, or somesuch.
> - in the test code, run two new threads, passing them two different
> "int" values; verify that the set_tl(value); can be matched with a
> CHECK_VALUE get_tl() == the value for that thread on the two threads.
Is the following extended test-case along the lines you have been thinking?
diff --git a/gcc/testsuite/jit.dg/test-thread-local.c
b/gcc/testsuite/jit.dg/test-thread-local.c
new file mode 100644
index 000000000..e21f144c4
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-thread-local.c
@@ -0,0 +1,161 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+int _Thread_local tl_c;
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ extern thread_local int tl_c;
+ static thread_ int tl_jit;
+ set_tl_jit (int v)
+ {
+ tl_jit = v;
+ }
+
+ int
+ get_tl_jit (void)
+ {
+ return tl_jit;
+ }
+
+ set_tl_c (int v)
+ {
+ tl_c = v;
+ }
+
+ int
+ get_tl_c (void)
+ {
+ return tl_c;
+ }
+ */
+ gcc_jit_type *the_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *void_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ gcc_jit_lvalue *tl =
+ gcc_jit_context_new_global (ctxt, NULL, GCC_JIT_GLOBAL_INTERNAL,
+ the_type, "tl_jit");
+ gcc_jit_lvalue_set_bool_thread_local (tl, 1);
+
+ gcc_jit_param *v =
+ gcc_jit_context_new_param (ctxt, NULL, the_type, "v");
+ gcc_jit_param *params[1] = {v};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ "set_tl_jit",
+ 1, params, 0);
+ gcc_jit_block *block =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block_add_assignment (block, NULL, tl,
+ gcc_jit_param_as_rvalue (v));
+ gcc_jit_block_end_with_void_return (block, NULL);
+
+ func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ the_type,
+ "get_tl_jit",
+ 0, NULL, 0);
+ block =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block_end_with_return (block, NULL,
+ gcc_jit_lvalue_as_rvalue (tl));
+
+ tl =
+ gcc_jit_context_new_global (ctxt, NULL, GCC_JIT_GLOBAL_IMPORTED,
+ the_type, "tl_c");
+ gcc_jit_lvalue_set_bool_thread_local (tl, 1);
+
+ v =
+ gcc_jit_context_new_param (ctxt, NULL, the_type, "v");
+ params[0] = v;
+ func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ "set_tl_c",
+ 1, params, 0);
+ block =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block_add_assignment (block, NULL, tl,
+ gcc_jit_param_as_rvalue (v));
+ gcc_jit_block_end_with_void_return (block, NULL);
+
+ func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ the_type,
+ "get_tl_c",
+ 0, NULL, 0);
+ block =
+ gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block_end_with_return (block, NULL,
+ gcc_jit_lvalue_as_rvalue (tl));
+}
+
+typedef void (*set_tl_fn_type) (int);
+typedef int (*get_tl_fn_type) (void);
+
+static set_tl_fn_type set_tl_jit, set_tl_c;
+static get_tl_fn_type get_tl_jit, get_tl_c;
+
+static void *
+test_thread_local_run (void *arg)
+{
+ set_tl_jit (43);
+ set_tl_c (101);
+ int val = get_tl_jit ();
+ CHECK_VALUE (val, 43);
+ val = get_tl_c ();
+ CHECK_VALUE (val, 101);
+ return NULL;
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+
+ CHECK_NON_NULL (result);
+
+ set_tl_jit =
+ (set_tl_fn_type) gcc_jit_result_get_code (result, "set_tl_jit");
+ get_tl_jit =
+ (get_tl_fn_type) gcc_jit_result_get_code (result, "get_tl_jit");
+ set_tl_c =
+ (set_tl_fn_type) gcc_jit_result_get_code (result, "set_tl_c");
+ get_tl_c =
+ (get_tl_fn_type) gcc_jit_result_get_code (result, "get_tl_c");
+
+ CHECK_NON_NULL (set_tl_jit);
+ CHECK_NON_NULL (get_tl_jit);
+ CHECK_NON_NULL (set_tl_c);
+ CHECK_NON_NULL (get_tl_c);
+
+ set_tl_jit (42);
+ set_tl_c (100);
+
+ pthread_t thread;
+ CHECK_VALUE (pthread_create(&thread, NULL, test_thread_local_run,
NULL), 0);
+ CHECK_VALUE (pthread_join(thread, NULL), 0);
+
+ int val = get_tl_jit ();
+ note ("get_tl_jit returned: %d", val);
+ CHECK_VALUE (val, 42);
+
+ val = get_tl_c ();
+ note ("get_tl_c returned: %d", val);
+ CHECK_VALUE (val, 100);
+}
> ...or somesuch, though the patch is in pretty good shape already.
Thanks! Your information at
https://gcc.gnu.org/onlinedocs/jit/internals/index.html has been
extremely helpful.
[...]
prev parent reply other threads:[~2019-01-08 21:06 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-01 0:00 Marc Nieper-Wißkirchen
2019-01-01 0:00 ` David Malcolm
2019-01-01 0:00 ` [committed] Fix jit test case (PR jit/88747) David Malcolm
2019-01-01 0:00 ` [PATCH][jit] Add thread-local globals to the libgccjit frontend Marc Nieper-Wißkirchen
2019-01-01 0:00 ` David Malcolm
2019-01-01 0:00 ` Marc Nieper-Wißkirchen [this message]
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=f81e88af-671d-9ad8-240f-0537684083f8@nieper-wisskirchen.de \
--to=marc@nieper-wisskirchen.de \
--cc=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jit@gcc.gnu.org \
--cc=marc.nieper+gnu@gmail.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).