impossible to step through wait_reading_process_output. */
#ifndef select
+int thread_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+ EMACS_TIME *);
+
static INLINE int
select_wrapper (n, rfd, wfd, xfd, tmo)
int n;
SELECT_TYPE *rfd, *wfd, *xfd;
EMACS_TIME *tmo;
{
- return select (n, rfd, wfd, xfd, tmo);
+ return thread_select (n, rfd, wfd, xfd, tmo);
}
#define select select_wrapper
#endif
#include "buffer.h"
#include "blockinput.h"
#include <pthread.h>
+#include "systime.h"
+#include "sysselect.h"
void mark_byte_stack P_ ((struct byte_stack *));
void mark_backtrace P_ ((struct backtrace *));
struct thread_state *it, *begin = NEXT_THREAD (current_thread);
#define CHECK_THREAD(T,B) \
- if (!other_threads_p () \
- || ((struct thread_state *)T)->nolock \
- || EQ (((struct thread_state *)T)->desired_buffer, \
- ((struct thread_state *)T)->m_current_buffer) \
- || EQ (B->owner, Qnil) \
+ if ((!other_threads_p () \
+ || ((struct thread_state *)T)->nolock \
+ || EQ (((struct thread_state *)T)->desired_buffer, \
+ ((struct thread_state *)T)->m_current_buffer) \
+ || EQ (B->owner, Qnil) \
/* We set the owner to Qt to mean it is being killed. */ \
- || EQ (B->owner, Qt)) \
+ || EQ (B->owner, Qt)) \
+ && !((struct thread_state *)T)->blocked) \
{ \
next_thread = ((struct thread_state *)T)->pthread_id; \
return; \
/* Schedule a new thread and block the caller until it is not scheduled
again. */
static inline void
-reschedule_and_wait (char *end)
+reschedule (char *end, int wait)
{
current_thread->stack_top = end;
if (!thread_inhibit_yield_p ())
if (next_thread != current_thread->pthread_id)
pthread_cond_broadcast (&buffer_cond);
+ if (!wait)
+ return;
+
pthread_mutex_unlock (&global_lock);
pthread_mutex_lock (&global_lock);
current_buffer->prev_owner = Qnil;
}
- reschedule_and_wait (end);
+ reschedule (end, 1);
/* FIXME: if buffer is killed */
new_buffer->prev_owner = new_buffer->owner;
&& !thread_bind_bufferlocal_p (current_thread))
thread_acquire_buffer (end, current_buffer);
else
- reschedule_and_wait (end);
+ reschedule (end, 1);
}
void
m_gcprolist));
new_thread->func = function;
+ new_thread->blocked = 0;
new_thread->nolock = !EQ (nolock, Qnil);
new_thread->initial_specpdl = Qnil;
new_thread->m_current_buffer = current_thread->m_current_buffer;
return Qnil;
}
+int
+thread_select (n, rfd, wfd, xfd, tmo)
+ int n;
+ SELECT_TYPE *rfd, *wfd, *xfd;
+ EMACS_TIME *tmo;
+{
+ char end;
+ int ret;
+ current_thread->blocked = 1;
+
+ reschedule (&end, 0);
+
+ pthread_mutex_unlock (&global_lock);
+
+ ret = select (n, rfd, wfd, xfd, tmo);
+ current_thread->blocked = 0;
+
+ pthread_mutex_lock (&global_lock);
+ pthread_cond_broadcast (&buffer_cond);
+
+ while (current_thread->pthread_id != next_thread)
+ pthread_cond_wait (&buffer_cond, &global_lock);
+
+ return ret;
+}
int
other_threads_p (void)
{
- return all_threads->next_thread != NULL;
+ int avail = 0;
+ struct thread_state *it = all_threads;
+ for (; it && avail < 2; it = it->next_thread)
+ if (!it->blocked)
+ avail++;
+
+ return avail > 1;
}
void
primary_thread.pthread_id = pthread_self ();
primary_thread.nolock = 0;
+ primary_thread.blocked = 0;
next_thread = primary_thread.pthread_id;
}