<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>