I think the restrictions do appear sound and reasonable.<br><br><div class="gmail_quote">On Wed, Jun 4, 2008 at 9:46 AM, Kazunori Asayama &lt;<a href="mailto:asayama@sm.sony.co.jp">asayama@sm.sony.co.jp</a>&gt; wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
This patch modifies the SPE event implementation of the libpse2 so<br>
that the libspe2 doesn&#39;t write stop_info on the pipe if no stop event<br>
handler is registered.<br>
<br>
As a result of this change, it becomes impossible to get stop info by<br>
spe_stop_info_read unless any stop event handlers are registered.<br>
<br>
Signed-off-by: Kazunori Asayama &lt;<a href="mailto:asayama@sm.sony.co.jp" target="_blank">asayama@sm.sony.co.jp</a>&gt;<br>
<br>
---<br>
I&#39;d like to ask opinions about the new restriction on usage of<br>
spe_stop_info_read; that is, applications can&#39;t get stop info via<br>
spe_stop_info_read without registration of stop event handler.<br>
<br>
In my personal opinion, this restriction is acceptable to actual<br>
applications because:<br>
<br>
&nbsp;a. If the thread which calls spe_context_run wants to get the stop<br>
 &nbsp; &nbsp;info, it&#39;s available via spe_context_run. So spe_stop_info_read<br>
 &nbsp; &nbsp;is unnecessary for the thread.<br>
<br>
&nbsp;b. If other threads want to get the stop info, the threads will call<br>
 &nbsp; &nbsp;spe_stop_info_read, and it will be necessary to wait for stop<br>
 &nbsp; &nbsp;events by spe_event_wait before spe_stop_info_read so that they<br>
 &nbsp; &nbsp;can know whether stop info is available or not<br>
 &nbsp; &nbsp;(spe_stop_info_read is non-blocking function).<br>
 &nbsp; &nbsp; &nbsp; &nbsp;In addition to that, spe_stop_info_read is valid only when<br>
 &nbsp; &nbsp;SPE_EVENTS_ENABLE is set to the SPE context. That implies that<br>
 &nbsp; &nbsp;spe_stop_info_read should be used with event processing.<br>
<br>
 &nbsp; &nbsp;I suppose that existing applications which use spe_stop_info_read<br>
 &nbsp; &nbsp;follow this scenario.<br>
---<br>
speevent/spe_event.c | &nbsp;156 ++++++++++++++++++++++++++++++++++++++++++---------<br>
speevent/speevent.h &nbsp;| &nbsp; &nbsp;3 2 files changed, 132 insertions(+), 27 deletions(-)<br>
<br>
Index: b/speevent/spe_event.c<br>
===================================================================<br>
--- a/speevent/spe_event.c &nbsp; &nbsp; &nbsp;2008-06-04 14:57:49.000000000 +0900<br>
+++ b/speevent/spe_event.c &nbsp; &nbsp; &nbsp;2008-06-04 16:10:45.000000000 +0900<br>
@@ -56,6 +56,74 @@ void _event_spe_context_unlock(spe_conte<br>
 &nbsp;pthread_mutex_unlock(&amp;__SPE_EVENT_CONTEXT_PRIV_GET(spe)-&gt;lock);<br>
}<br>
<br>
+static void stop_event_lock(spe_context_event_priv_ptr_t evctx)<br>
+{<br>
+ &nbsp;pthread_mutex_lock(&amp;evctx-&gt;stop_event_lock);<br>
+}<br>
+<br>
+static void stop_event_unlock(spe_context_event_priv_ptr_t evctx)<br>
+{<br>
+ &nbsp;pthread_mutex_unlock(&amp;evctx-&gt;stop_event_lock);<br>
+}<br>
+<br>
+static int stop_event_pipe_close(spe_context_event_priv_ptr_t evctx)<br>
+{<br>
+ &nbsp;if (evctx-&gt;stop_event_pipe[0] != -1) {<br>
+ &nbsp; &nbsp;close(evctx-&gt;stop_event_pipe[0]);<br>
+ &nbsp; &nbsp;evctx-&gt;stop_event_pipe[0] = -1;<br>
+ &nbsp;}<br>
+ &nbsp;if (evctx-&gt;stop_event_pipe[1] != -1) {<br>
+ &nbsp; &nbsp;close(evctx-&gt;stop_event_pipe[1]);<br>
+ &nbsp; &nbsp;evctx-&gt;stop_event_pipe[1] = -1;<br>
+ &nbsp;}<br>
+<br>
+ &nbsp;return 0;<br>
+}<br>
+<br>
+static int stop_event_pipe_open(spe_context_event_priv_ptr_t evctx)<br>
+{<br>
+ &nbsp;int rc;<br>
+<br>
+ &nbsp;rc = pipe(evctx-&gt;stop_event_pipe);<br>
+ &nbsp;if (rc == -1) {<br>
+ &nbsp; &nbsp;return -1;<br>
+ &nbsp;}<br>
+ &nbsp;rc = fcntl(evctx-&gt;stop_event_pipe[0], F_GETFL);<br>
+ &nbsp;if (rc != -1) {<br>
+ &nbsp; &nbsp;rc = fcntl(evctx-&gt;stop_event_pipe[0], F_SETFL, rc | O_NONBLOCK);<br>
+ &nbsp;}<br>
+ &nbsp;if (rc == -1) {<br>
+ &nbsp; &nbsp;stop_event_pipe_close(evctx);<br>
+ &nbsp; &nbsp;return -1;<br>
+ &nbsp;}<br>
+<br>
+ &nbsp;return 0;<br>
+}<br>
+<br>
+static int stop_event_pipe_acquire(spe_context_event_priv_ptr_t evctx)<br>
+{<br>
+ &nbsp;if (evctx-&gt;stop_event_handler_count == 0) {<br>
+ &nbsp; &nbsp;if (stop_event_pipe_open(evctx) == -1) {<br>
+ &nbsp; &nbsp; &nbsp;return -1;<br>
+ &nbsp; &nbsp;}<br>
+ &nbsp;}<br>
+<br>
+ &nbsp;evctx-&gt;stop_event_handler_count++;<br>
+<br>
+ &nbsp;return 0;<br>
+}<br>
+<br>
+static int stop_event_pipe_release(spe_context_event_priv_ptr_t evctx)<br>
+{<br>
+ &nbsp;evctx-&gt;stop_event_handler_count--;<br>
+<br>
+ &nbsp;if (evctx-&gt;stop_event_handler_count == 0) {<br>
+ &nbsp; &nbsp;stop_event_pipe_close(evctx);<br>
+ &nbsp;}<br>
+<br>
+ &nbsp;return 0;<br>
+}<br>
+<br>
int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo)<br>
{<br>
 &nbsp;spe_context_event_priv_ptr_t evctx;<br>
@@ -64,13 +132,20 @@ int _event_spe_stop_info_read (spe_conte<br>
 &nbsp;size_t total;<br>
 &nbsp; &nbsp;evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);<br>
+<br>
+ &nbsp;stop_event_lock(evctx); /* for atomic read */<br>
+<br>
 &nbsp;fd = evctx-&gt;stop_event_pipe[0];<br>
<br>
- &nbsp;pthread_mutex_lock(&amp;evctx-&gt;stop_event_read_lock); /* for atomic read */<br>
+ &nbsp;if (fd == -1) { /* no stop event handler */<br>
+ &nbsp; &nbsp;stop_event_unlock(evctx);<br>
+ &nbsp; &nbsp;errno = EAGAIN;<br>
+ &nbsp; &nbsp;return -1;<br>
+ &nbsp;}<br>
<br>
 &nbsp;rc = read(fd, stopinfo, sizeof(*stopinfo));<br>
 &nbsp;if (rc == -1) {<br>
- &nbsp; &nbsp;pthread_mutex_unlock(&amp;evctx-&gt;stop_event_read_lock);<br>
+ &nbsp; &nbsp;stop_event_unlock(evctx);<br>
 &nbsp; &nbsp;return -1;<br>
 &nbsp;}<br>
<br>
@@ -98,7 +173,7 @@ int _event_spe_stop_info_read (spe_conte<br>
 &nbsp; &nbsp;}<br>
 &nbsp;}<br>
<br>
- &nbsp;pthread_mutex_unlock(&amp;evctx-&gt;stop_event_read_lock);<br>
+ &nbsp;stop_event_unlock(evctx);<br>
<br>
 &nbsp;return rc == -1 ? -1 : 0;<br>
}<br>
@@ -248,6 +323,15 @@ int _event_spe_event_handler_register(sp<br>
 &nbsp;}<br>
<br>
 &nbsp;if (event-&gt;events &amp; SPE_EVENT_SPE_STOPPED) {<br>
+ &nbsp; &nbsp;/* prevent reading stop info while registering */<br>
+ &nbsp; &nbsp;stop_event_lock(evctx);<br>
+<br>
+ &nbsp; &nbsp;if (stop_event_pipe_acquire(evctx) == -1) {<br>
+ &nbsp; &nbsp; &nbsp;stop_event_unlock(evctx);<br>
+ &nbsp; &nbsp; &nbsp;_event_spe_context_unlock(event-&gt;spe);<br>
+ &nbsp; &nbsp; &nbsp;return -1;<br>
+ &nbsp; &nbsp;}<br>
+<br>
 &nbsp; &nbsp;fd = evctx-&gt;stop_event_pipe[0];<br>
 &nbsp; &nbsp; &nbsp; &nbsp;ev_buf = &amp;evctx-&gt;events[__SPE_EVENT_SPE_STOPPED];<br>
@@ -257,9 +341,13 @@ int _event_spe_event_handler_register(sp<br>
 &nbsp; &nbsp;ep_event.events = EPOLLIN;<br>
 &nbsp; &nbsp;ep_event.data.ptr = ev_buf;<br>
 &nbsp; &nbsp;if (epoll_ctl(epfd, ep_op, fd, &amp;ep_event) == -1) {<br>
+ &nbsp; &nbsp; &nbsp;stop_event_pipe_release(evctx);<br>
+ &nbsp; &nbsp; &nbsp;stop_event_unlock(evctx);<br>
 &nbsp; &nbsp; &nbsp;_event_spe_context_unlock(event-&gt;spe);<br>
 &nbsp; &nbsp; &nbsp;return -1;<br>
 &nbsp; &nbsp;}<br>
+<br>
+ &nbsp; &nbsp;stop_event_unlock(evctx);<br>
 &nbsp;}<br>
<br>
 &nbsp;_event_spe_context_unlock(event-&gt;spe);<br>
@@ -340,12 +428,20 @@ int _event_spe_event_handler_deregister(<br>
 &nbsp;}<br>
 &nbsp; &nbsp;if (event-&gt;events &amp; SPE_EVENT_SPE_STOPPED) {<br>
+ &nbsp; &nbsp;/* prevent reading stop info while unregistering */<br>
+ &nbsp; &nbsp;stop_event_lock(evctx);<br>
+<br>
 &nbsp; &nbsp;fd = evctx-&gt;stop_event_pipe[0];<br>
 &nbsp; &nbsp;if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) {<br>
+ &nbsp; &nbsp; &nbsp;stop_event_unlock(evctx);<br>
 &nbsp; &nbsp; &nbsp;_event_spe_context_unlock(event-&gt;spe);<br>
 &nbsp; &nbsp; &nbsp;return -1;<br>
 &nbsp; &nbsp;}<br>
 &nbsp; &nbsp;evctx-&gt;events[__SPE_EVENT_SPE_STOPPED].events = 0;<br>
+<br>
+ &nbsp; &nbsp;stop_event_pipe_release(evctx);<br>
+<br>
+ &nbsp; &nbsp;stop_event_unlock(evctx);<br>
 &nbsp;}<br>
<br>
 &nbsp;_event_spe_context_unlock(event-&gt;spe);<br>
@@ -424,12 +520,11 @@ int _event_spe_context_finalize(spe_cont<br>
<br>
 &nbsp;evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);<br>
 &nbsp;__SPE_EVENT_CONTEXT_PRIV_SET(spe, NULL);<br>
- &nbsp;- &nbsp;close(evctx-&gt;stop_event_pipe[0]);<br>
- &nbsp;close(evctx-&gt;stop_event_pipe[1]);<br>
+<br>
+ &nbsp;stop_event_pipe_close(evctx);<br>
<br>
 &nbsp;pthread_mutex_destroy(&amp;evctx-&gt;lock);<br>
- &nbsp;pthread_mutex_destroy(&amp;evctx-&gt;stop_event_read_lock);<br>
+ &nbsp;pthread_mutex_destroy(&amp;evctx-&gt;stop_event_lock);<br>
<br>
 &nbsp;free(evctx);<br>
<br>
@@ -439,7 +534,6 @@ int _event_spe_context_finalize(spe_cont<br>
struct spe_context_event_priv * _event_spe_context_initialize(spe_context_ptr_t spe)<br>
{<br>
 &nbsp;spe_context_event_priv_ptr_t evctx;<br>
- &nbsp;int rc;<br>
 &nbsp;int i;<br>
<br>
 &nbsp;evctx = calloc(1, sizeof(*evctx));<br>
@@ -447,29 +541,16 @@ struct spe_context_event_priv * _event_s<br>
 &nbsp; &nbsp;return NULL;<br>
 &nbsp;}<br>
<br>
- &nbsp;rc = pipe(evctx-&gt;stop_event_pipe);<br>
- &nbsp;if (rc == -1) {<br>
- &nbsp; &nbsp;free(evctx);<br>
- &nbsp; &nbsp;return NULL;<br>
- &nbsp;}<br>
- &nbsp;rc = fcntl(evctx-&gt;stop_event_pipe[0], F_GETFL);<br>
- &nbsp;if (rc != -1) {<br>
- &nbsp; &nbsp;rc = fcntl(evctx-&gt;stop_event_pipe[0], F_SETFL, rc | O_NONBLOCK);<br>
- &nbsp;}<br>
- &nbsp;if (rc == -1) {<br>
- &nbsp; &nbsp;close(evctx-&gt;stop_event_pipe[0]);<br>
- &nbsp; &nbsp;close(evctx-&gt;stop_event_pipe[1]);<br>
- &nbsp; &nbsp;free(evctx);<br>
- &nbsp; &nbsp;errno = EIO;<br>
- &nbsp; &nbsp;return NULL;<br>
- &nbsp;}<br>
+ &nbsp;/* the pipe will be created when any stop event handler is registered */<br>
+ &nbsp;evctx-&gt;stop_event_pipe[0] = -1;<br>
+ &nbsp;evctx-&gt;stop_event_pipe[1] = -1;<br>
<br>
 &nbsp;for (i = 0; i &lt; sizeof(evctx-&gt;events) / sizeof(evctx-&gt;events[0]); i++) {<br>
 &nbsp; &nbsp;evctx-&gt;events[i].spe = spe;<br>
 &nbsp;}<br>
<br>
 &nbsp;pthread_mutex_init(&amp;evctx-&gt;lock, NULL);<br>
- &nbsp;pthread_mutex_init(&amp;evctx-&gt;stop_event_read_lock, NULL);<br>
+ &nbsp;pthread_mutex_init(&amp;evctx-&gt;stop_event_lock, NULL);<br>
<br>
 &nbsp;return evctx;<br>
}<br>
@@ -479,17 +560,40 @@ int _event_spe_context_run &nbsp; &nbsp; &nbsp; &nbsp;(spe_context_<br>
 &nbsp;spe_context_event_priv_ptr_t evctx;<br>
 &nbsp;spe_stop_info_t stopinfo_buf;<br>
 &nbsp;int rc;<br>
+ &nbsp;int errno_saved;<br>
+ &nbsp;int fd;<br>
<br>
 &nbsp;if (!stopinfo) {<br>
 &nbsp; &nbsp;stopinfo = &amp;stopinfo_buf;<br>
 &nbsp;}<br>
 &nbsp;rc = _base_spe_context_run(spe, entry, runflags, argp, envp, stopinfo);<br>
+ &nbsp;errno_saved = errno;<br>
<br>
 &nbsp;evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe);<br>
- &nbsp;if (write(evctx-&gt;stop_event_pipe[1], stopinfo, sizeof(*stopinfo)) != sizeof(*stopinfo)) {<br>
+<br>
+ &nbsp;stop_event_lock(evctx);<br>
+<br>
+ &nbsp;fd = evctx-&gt;stop_event_pipe[1];<br>
+ &nbsp;/* don&#39;t write stop info if no stop event handler is registered */<br>
+ &nbsp;if (fd == -1) {<br>
+ &nbsp; &nbsp;stop_event_unlock(evctx);<br>
+ &nbsp; &nbsp;return rc;<br>
+ &nbsp;}<br>
+<br>
+ &nbsp;stop_event_pipe_acquire(evctx); /* to avoid closing the pipe after unlocked */<br>
+ &nbsp;stop_event_unlock(evctx); /* unlock here to avoid deadlocks */<br>
+<br>
+ &nbsp;if (write(fd, stopinfo, sizeof(*stopinfo)) != sizeof(*stopinfo)) {<br>
 &nbsp; &nbsp;/* error check. */<br>
 &nbsp;}<br>
<br>
+ &nbsp;/* release the pipe */<br>
+ &nbsp;stop_event_lock(evctx);<br>
+ &nbsp;stop_event_pipe_release(evctx);<br>
+ &nbsp;stop_event_unlock(evctx);<br>
+<br>
+ &nbsp;errno = errno_saved;<br>
+<br>
 &nbsp;return rc;<br>
}<br>
<br>
Index: b/speevent/speevent.h<br>
===================================================================<br>
--- a/speevent/speevent.h &nbsp; &nbsp; &nbsp; 2008-06-04 14:57:49.000000000 +0900<br>
+++ b/speevent/speevent.h &nbsp; &nbsp; &nbsp; 2008-06-04 14:57:54.000000000 +0900<br>
@@ -35,8 +35,9 @@ enum __spe_event_types {<br>
typedef struct spe_context_event_priv<br>
{<br>
 &nbsp;pthread_mutex_t lock;<br>
- &nbsp;pthread_mutex_t stop_event_read_lock;<br>
+ &nbsp;pthread_mutex_t stop_event_lock;<br>
 &nbsp;int stop_event_pipe[2];<br>
+ &nbsp;int stop_event_handler_count;<br>
 &nbsp;spe_event_unit_t events[__NUM_SPE_EVENT_TYPES];<br>
} spe_context_event_priv_t, *spe_context_event_priv_ptr_t;<br>
<br>
</blockquote></div><br>