<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Sep 25, 2019 at 8:13 PM Richard Palethorpe <<a href="mailto:rpalethorpe@suse.de">rpalethorpe@suse.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail_default" style="font-size:small">...</span><br>
I'm not sure what you are saying. However you could do something like<br>
this (I haven't tested it):<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">I misunderstood your words in the last mail, sorry about that.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
struct tst_fzsync_run_thread<br>
{<br>
        void *(*run)(void *);<br>
        void *arg;<br>
};<br>
<br>
static void tst_fzsync_thread_wrapper(void *arg)<br>
{<br>
        struct tst_fzsync_run_thread t = *(struct tst_fzsync_run_thread *)arg;<br>
<br>
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS);<br>
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE);<br>
<br>
        t.run(t.arg);<br>
}<br>
<br>
static void tst_fzsync_pair_reset(..., struct tst_fzsync_run_thread *run_b)<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">I'd like to keep the tst_fzync_pair_reset() API no change to user.</div></div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">The patch v4.1 like below, is there any improper place in usage?</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">@@ -218,12 +219,36 @@ static void tst_fzsync_pair_init(struct tst_fzsync_pair *pair)<br> static void tst_fzsync_pair_cleanup(struct tst_fzsync_pair *pair)<br> {<br>        if (pair->thread_b) {<br>-               tst_atomic_store(1, &pair->exit);<br>+               /* Revoke thread B if parent hits accidental break */<br>+               if (!pair->exit) {<br>+                       tst_atomic_store(1, &pair->exit);<br>+                       usleep(100000);<br>+                       pthread_cancel(pair->thread_b);<br>+               }<br>                SAFE_PTHREAD_JOIN(pair->thread_b, NULL);<br>                pair->thread_b = 0;<br>        }<br> }<br> <br>+/** To store the run_b pointer and pass to tst_fzsync_thread_wrapper */<br>+struct tst_fzsync_run_thread {<br>+       void *(*func)(void *);<br>+       void *arg;<br>+};<br>+<br>+/**<br>+ * Wrap run_b for tst_fzsync_pair_reset to enable pthread cancel<br>+ * at the start of the thread B.<br>+ */<br>+static void *tst_fzsync_thread_wrapper(void *run_thread)<br>+{<br>+       struct tst_fzsync_run_thread t = *(struct tst_fzsync_run_thread *)run_thread;<br>+<br>+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);<br>+       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);<br>+       return t.func(t.arg);<br>+}<br>+<br> /**<br>  * Zero some stat fields<br>  *<br>@@ -271,8 +296,10 @@ static void tst_fzsync_pair_reset(struct tst_fzsync_pair *pair,<br>        pair->a_cntr = 0;<br>        pair->b_cntr = 0;<br>        pair->exit = 0;<br>-       if (run_b)<br>-               SAFE_PTHREAD_CREATE(&pair->thread_b, 0, run_b, 0);<br>+       if (run_b) {<br>+               struct tst_fzsync_run_thread wrap_run_b = {.func = run_b, .arg = NULL};<br>+               SAFE_PTHREAD_CREATE(&pair->thread_b, 0, tst_fzsync_thread_wrapper, &wrap_run_b);<br>+       }<br> <br>        pair->exec_time_start = (float)tst_timeout_remaining();<br> }<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Note that in any case you can't reliably cast a function pointer to a<br>
void pointer without some magic. I am guessing wrapping it in a struct<br>
is the clearest way to do it.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">Good to know this, I searched on google and confirmed that the C standard does not allow to cast function pointer to void*, thanks!</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
You can remove the arg altogether, but I kept it because we have a<br>
struct anyway to wrap the function pointer.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">Yes, to keep it make the wrapper struct is clear to understand.</div></div></div><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div>