From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Ken Raeburn Newsgroups: gmane.lisp.guile.devel Subject: entering and leaving guile mode, and GC stack protection (was Re: guile performance - Ackermann function: way slower than emacs, slower still if compiled) Date: Thu, 6 Aug 2009 12:30:53 -0400 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 (Apple Message framework v935.3) Content-Type: multipart/mixed; boundary=Apple-Mail-66-686113847 X-Trace: ger.gmane.org 1249576305 9263 80.91.229.12 (6 Aug 2009 16:31:45 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 6 Aug 2009 16:31:45 +0000 (UTC) To: guile-devel Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Aug 06 18:31:38 2009 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1MZ5sO-0002BF-Mc for guile-devel@m.gmane.org; Thu, 06 Aug 2009 18:31:38 +0200 Original-Received: from localhost ([127.0.0.1]:32916 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MZ5sO-0001ly-0p for guile-devel@m.gmane.org; Thu, 06 Aug 2009 12:31:36 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MZ5sE-0001fQ-Sy for guile-devel@gnu.org; Thu, 06 Aug 2009 12:31:26 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MZ5sB-0001cq-2u for guile-devel@gnu.org; Thu, 06 Aug 2009 12:31:26 -0400 Original-Received: from [199.232.76.173] (port=46683 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MZ5sA-0001cf-HO for guile-devel@gnu.org; Thu, 06 Aug 2009 12:31:22 -0400 Original-Received: from splat.raeburn.org ([69.25.196.39]:61782 helo=raeburn.org) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1MZ5rm-00024n-35 for guile-devel@gnu.org; Thu, 06 Aug 2009 12:31:22 -0400 Original-Received: from [10.0.0.172] (squish.raeburn.org [10.0.0.172]) by raeburn.org (8.14.3/8.14.1) with ESMTP id n76GUrVW010536; Thu, 6 Aug 2009 12:30:53 -0400 (EDT) In-Reply-To: X-Mailer: Apple Mail (2.935.3) X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:9036 Archived-At: --Apple-Mail-66-686113847 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit On Aug 5, 2009, at 10:06, I wrote: > (3) My four-year-old comments on scm_enter/leave_guile, recorded in > threads.c around line 300, still stand.... Those functions really > ought to go away. At least they're confined to one file, now. Some > of it looks a little messy, but I can probably get rid of some of > the uses.... I've made a bit of progress on this. The basic issue is that the way scm_enter/leave_guile are implemented, they make some bad assumptions about how the stack will be laid out and where SCM values might get stored. The right way to tackle it, I believe, is to only provide functions like scm_without_guile that make callbacks, and get complete control over the transitions both into and out of guile mode so they can better manage the stack layout. It's not just scm_leave_guile() that needs to go away and be replaced by a different interface, but suspend() and anything that calls it without pairing it up nicely with resume(). Functions pairing them up need updating too, but not their interfaces; the code in between suspend and resume just needs to be pulled out into a callback function. So my changes in this first cut are basically: * New function while_suspended takes callback and replaces suspend...resume sequence; used only in scm_i_thread_sleep_for_gc now but scm_without_guile is an obvious additional place, when we can get rid of scm_leave_guile. * New helper function scm_without_guile_int, like scm_without_guile but return type is int. Static for now; would it be useful to export? * Replace scm_i_thread_put_to_sleep and _wake_up with scm_i_with_threads_sleeping which takes a callback. Change resize_all_states, scm_i_gc, scm_i_string_writable_chars accordingly. * Use scm_without_guile(_int) in scm_std_select, scm_pthread_mutex_lock (assumes my earlier change!), scm_pthread_cond_wait, scm_pthread_cond_timedwait, scm_i_with_threads_sleeping. There are still unpaired uses of scm_leave_guile and scm_enter_guile that I'm going to have to look at more closely before I can figure out what to do about them. And the problematic suspend() function itself is still there, but once its usage is confined to while_suspended, it'll be easier to clean up. Comments? Ken --Apple-Mail-66-686113847 Content-Disposition: attachment; filename=guile-patch.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="guile-patch.diff" Content-Transfer-Encoding: quoted-printable diff=20--git=20a/libguile/fluids.c=20b/libguile/fluids.c=0Aindex=20= bcd04c4..e532e39=20100644=0A---=20a/libguile/fluids.c=0A+++=20= b/libguile/fluids.c=0A@@=20-87,6=20+87,27=20@@=20static=20scm_t_bits=20= tc16_dynamic_state;=0A=20static=20SCM=20all_dynamic_states=20=3D=20= SCM_EOL;=0A=20static=20SCM=20all_fluids=20=3D=20SCM_EOL;=0A=20=0A+static=20= void=0A+update_all_states=20(void=20*p)=0A+{=0A+=20=20SCM=20new_vectors=20= =3D=20*(SCM=20*)p;=0A+=20=20SCM=20state;=0A+=0A+=20=20for=20(state=20=3D=20= all_dynamic_states;=20!scm_is_null=20(state);=0A+=20=20=20=20=20=20=20= state=20=3D=20DYNAMIC_STATE_NEXT=20(state))=0A+=20=20=20=20{=0A+=20=20=20= =20=20=20SCM=20old_fluids=20=3D=20DYNAMIC_STATE_FLUIDS=20(state);=0A+=20=20= =20=20=20=20SCM=20new_fluids=20=3D=20SCM_CAR=20(new_vectors);=0A+=20=20=20= =20=20=20size_t=20i,=20old_len=20=3D=20SCM_SIMPLE_VECTOR_LENGTH=20= (old_fluids);=0A+=0A+=20=20=20=20=20=20for=20(i=20=3D=200;=20i=20<=20= old_len;=20i++)=0A+=09SCM_SIMPLE_VECTOR_SET=20(new_fluids,=20i,=0A+=09=09= =09=20=20=20=20=20=20=20SCM_SIMPLE_VECTOR_REF=20(old_fluids,=20i));=0A+=20= =20=20=20=20=20SET_DYNAMIC_STATE_FLUIDS=20(state,=20new_fluids);=0A+=20=20= =20=20=20=20new_vectors=20=3D=20SCM_CDR=20(new_vectors);=0A+=20=20=20=20= }=0A+}=0A+=0A=20/*=20Make=20sure=20that=20all=20states=20have=20the=20= right=20size.=20=20This=20must=20be=20called=0A=20=20=20=20while=20= fluid_admin_mutex=20is=20held.=0A=20*/=0A@@=20-112,21=20+133,7=20@@=20= resize_all_states=20()=0A=20=09=09=09=09=09=20=20=20=20=20=20=20= SCM_BOOL_F),=0A=20=09=09=09=20=20=20=20new_vectors);=0A=20=0A-=20=20= scm_i_thread_put_to_sleep=20();=0A-=20=20for=20(state=20=3D=20= all_dynamic_states;=20!scm_is_null=20(state);=0A-=20=20=20=20=20=20=20= state=20=3D=20DYNAMIC_STATE_NEXT=20(state))=0A-=20=20=20=20{=0A-=20=20=20= =20=20=20SCM=20old_fluids=20=3D=20DYNAMIC_STATE_FLUIDS=20(state);=0A-=20=20= =20=20=20=20SCM=20new_fluids=20=3D=20SCM_CAR=20(new_vectors);=0A-=20=20=20= =20=20=20size_t=20i,=20old_len=20=3D=20SCM_SIMPLE_VECTOR_LENGTH=20= (old_fluids);=0A-=0A-=20=20=20=20=20=20for=20(i=20=3D=200;=20i=20<=20= old_len;=20i++)=0A-=09SCM_SIMPLE_VECTOR_SET=20(new_fluids,=20i,=0A-=09=09= =09=20=20=20=20=20=20=20SCM_SIMPLE_VECTOR_REF=20(old_fluids,=20i));=0A-=20= =20=20=20=20=20SET_DYNAMIC_STATE_FLUIDS=20(state,=20new_fluids);=0A-=20=20= =20=20=20=20new_vectors=20=3D=20SCM_CDR=20(new_vectors);=0A-=20=20=20=20= }=0A-=20=20scm_i_thread_wake_up=20();=0A+=20=20= scm_i_with_threads_sleeping=20(update_all_states,=20&new_vectors);=0A=20= }=0A=20=0A=20/*=20This=20is=20called=20during=20GC,=20that=20is,=20while=20= being=20single=20threaded.=0Adiff=20--git=20a/libguile/gc.c=20= b/libguile/gc.c=0Aindex=20b7a3bf0..818aec6=20100644=0A---=20= a/libguile/gc.c=0A+++=20b/libguile/gc.c=0A@@=20-561,18=20+561,20=20@@=20= scm_check_deprecated_memory_return=20()=0A=20=0A=20long=20int=20= scm_i_last_marked_cell_count;=0A=20=0A-/*=20Must=20be=20called=20while=20= holding=20scm_i_sweep_mutex.=0A+/*=20Must=20be=20called=20while=20= holding=20scm_i_sweep_mutex=20and=20with=20all=20threads=0A+=20=20=20= sleeping.=0A=20=0A=20=20=20=20This=20function=20is=20fairly=20long,=20= but=20it=20touches=20various=20global=0A=20=20=20=20variables.=20To=20= not=20obscure=20the=20side=20effects=20on=20global=20variables,=0A=20=20=20= =20this=20function=20has=20not=20been=20split=20up.=0A=20=20*/=0A-void=0A= -scm_i_gc=20(const=20char=20*what)=0A+static=20void=0A+scm_i_gc_1=20= (void=20*p)=0A=20{=0A=20=20=20unsigned=20long=20t_before_gc=20=3D=200;=0A= -=20=20=0A-=20=20scm_i_thread_put_to_sleep=20();=0A+#ifdef=20DEBUGINFO=0A= +=20=20const=20char=20*what=20=3D=20*(const=20char=20*)p;=0A+#endif=0A=20= =20=20=0A=20=20=20scm_c_hook_run=20(&scm_before_gc_c_hook,=200);=0A=20=0A= @@=20-678,8=20+680,6=20@@=20scm_i_gc=20(const=20char=20*what)=0A=20=20=20= =20=20=20the=20time=20taken.=0A=20=20=20*/=0A=20=20=20scm_gc_time_taken=20= +=3D=20(scm_c_get_internal_run_time=20()=20-=20t_before_gc);=0A-=20=20=20= =20=0A-=20=20scm_i_thread_wake_up=20();=0A=20=20=20/*=0A=20=20=20=20=20= For=20debugging=20purposes,=20you=20could=20do=0A=20=20=20=20=20= scm_i_sweep_all_segments=20("debug"),=20but=20then=20the=20remains=20of=20= the=0A@@=20-687,6=20+687,11=20@@=20scm_i_gc=20(const=20char=20*what)=0A=20= =20=20=20*/=0A=20}=0A=20=0A+void=0A+scm_i_gc=20(const=20char=20*what)=0A= +{=0A+=20=20scm_i_with_threads_sleeping=20(scm_i_gc_1,=20&what);=0A+}=0A=20= =0A=20=0C=0A=20/*=20{GC=20Protection=20Helper=20Functions}=0Adiff=20= --git=20a/libguile/strings.c=20b/libguile/strings.c=0Aindex=20= 4e21f3e..ab8cd14=20100644=0A---=20a/libguile/strings.c=0A+++=20= b/libguile/strings.c=0A@@=20-339,6=20+339,21=20@@=20scm_i_string_chars=20= (SCM=20str)=0A=20=20=20return=20STRINGBUF_CHARS=20(buf)=20+=20start;=0A=20= }=0A=20=0A+struct=20replace_data=20{=0A+=20=20SCM=20str,=20new_buf;=0A+=20= =20size_t=20start;=0A+};=0A+=0A+static=20void=0A+replace_stringbuf_data=20= (void=20*p)=0A+{=0A+=20=20struct=20replace_data=20*r=20=3D=20p;=0A+=0A+=20= =20SET_STRING_STRINGBUF=20(r->str,=20r->new_buf);=0A+=20=20r->start=20=3D=20= STRING_START=20(r->str);=0A+=20=20SET_STRING_START=20(r->str,=200);=0A+}=0A= +=0A=20char=20*=0A=20scm_i_string_writable_chars=20(SCM=20orig_str)=0A=20= {=0A@@=20-357,19=20+372,17=20@@=20scm_i_string_writable_chars=20(SCM=20= orig_str)=0A=20=0A=20=20=20=20=20=20=20size_t=20len=20=3D=20= STRING_LENGTH=20(str);=0A=20=20=20=20=20=20=20SCM=20new_buf;=0A+=20=20=20= =20=20=20struct=20replace_data=20r;=0A=20=0A=20=20=20=20=20=20=20= scm_i_pthread_mutex_unlock=20(&stringbuf_write_mutex);=0A=20=0A=20=20=20=20= =20=20=20new_buf=20=3D=20make_stringbuf=20(len);=0A=20=20=20=20=20=20=20= memcpy=20(STRINGBUF_CHARS=20(new_buf),=0A=20=09=20=20=20=20=20=20= STRINGBUF_CHARS=20(buf)=20+=20STRING_START=20(str),=20len);=0A-=0A-=20=20= =20=20=20=20scm_i_thread_put_to_sleep=20();=0A-=20=20=20=20=20=20= SET_STRING_STRINGBUF=20(str,=20new_buf);=0A-=20=20=20=20=20=20start=20-=3D= =20STRING_START=20(str);=0A-=20=20=20=20=20=20SET_STRING_START=20(str,=20= 0);=0A-=20=20=20=20=20=20scm_i_thread_wake_up=20();=0A-=0A+=20=20=20=20=20= =20r.str=20=3D=20str;=0A+=20=20=20=20=20=20r.new_buf=20=3D=20new_buf;=0A= +=20=20=20=20=20=20scm_i_with_threads_sleeping=20= (replace_stringbuf_data,=20&r);=0A+=20=20=20=20=20=20start=20-=3D=20= r.start;=0A=20=20=20=20=20=20=20buf=20=3D=20new_buf;=0A=20=0A=20=20=20=20= =20=20=20scm_i_pthread_mutex_lock=20(&stringbuf_write_mutex);=0Adiff=20= --git=20a/libguile/threads.c=20b/libguile/threads.c=0Aindex=20= 8458a60..a2a98f3=20100644=0A---=20a/libguile/threads.c=0A+++=20= b/libguile/threads.c=0A@@=20-428,6=20+428,25=20@@=20suspend=20(void)=0A=20= =20=20setjmp=20(t->regs);=0A=20=20=20return=20t;=0A=20}=0A+=20=20=0A+=0A= +#if=20__GNUC__=20>=203=20||=20(__GNUC__=20=3D=3D=203=20&&=20= __GNUC_MINOR__=20>=3D=201)=0A+/*=20For=20paranoia's=20sake,=20make=20= sure=20the=20stack=20slot=20we=20take=20the=20address=0A+=20=20=20of=20= is=20allocated=20after=20(deeper=20on=20the=20stack)=20than=20anything=20= from=20the=0A+=20=20=20parent,=20by=20not=20permitting=20inline=20= expansion=20and=20thus=20possible=0A+=20=20=20rearranging=20of=20things=20= within=20the=20caller's=20stack=20frame.=20=20*/=0A+static=20void=0A= +while_suspended=20(void=20(*func)(void=20*,=20scm_i_thread=20*),=20void=20= *data)=0A+=20=20__attribute__((noinline));=0A+#endif=0A+=0A+static=20= void=0A+while_suspended=20(void=20(*func)(void=20*,=20scm_i_thread=20*),=20= void=20*data)=0A+{=0A+=20=20scm_i_thread=20*t=20=3D=20suspend=20();=0A+=20= =20func=20(data,=20t);=0A+=20=20resume=20(t);=0A+}=0A=20=0A=20static=20= scm_t_guile_ticket=0A=20scm_leave_guile=20()=0A@@=20-870,6=20+889,20=20= @@=20scm_without_guile=20(void=20*(*func)(void=20*),=20void=20*data)=0A=20= =20=20return=20res;=0A=20}=0A=20=0A+/*=20Internal=20helper=20function=20= --=20like=20scm_without_guile,=20but=20for=20various=0A+=20=20=20cases=20= in=20this=20file=20where=20we=20actually=20want=20to=20return=20an=20= int,=20not=0A+=20=20=20a=20pointer.=20=20*/=0A+static=20int=0A= +scm_without_guile_int=20(int=20(*func)(void=20*),=20void=20*data)=0A+{=0A= +=20=20int=20res;=0A+=20=20scm_t_guile_ticket=20t;=0A+=20=20t=20=3D=20= scm_leave_guile=20();=0A+=20=20res=20=3D=20func=20(data);=0A+=20=20= scm_enter_guile=20(t);=0A+=20=20return=20res;=0A+}=0A+=0A=20/***=20= Thread=20creation=20*/=0A=20=0A=20typedef=20struct=20{=0A@@=20-1769,6=20= +1802,28=20@@=20scm_threads_mark_stacks=20(void)=0A=20=0A=20/***=20= Select=20*/=0A=20=0A+struct=20select_callback_data=20{=0A+=20=20= SELECT_TYPE=20*readfds,=20*writefds,=20*exceptfds;=0A+=20=20struct=20= timeval=20*timeout;=0A+=20=20scm_i_thread=20*t;=0A+=20=20int=20nfds,=20= wakeup_fd,=20eno;=0A+};=0A+=0A+static=20int=0A+select_callback=20(void=20= *p)=0A+{=0A+=20=20struct=20select_callback_data=20*cb=20=3D=20p;=0A+=20=20= int=20res;=0A+=0A+=20=20FD_SET=20(cb->wakeup_fd,=20cb->readfds);=0A+=20=20= if=20(cb->wakeup_fd=20>=3D=20cb->nfds)=0A+=20=20=20=20cb->nfds=20=3D=20= cb->wakeup_fd+1;=0A+=20=20res=20=3D=20select=20(cb->nfds,=20cb->readfds,=20= cb->writefds,=20cb->exceptfds,=20cb->timeout);=0A+=20=20cb->t->sleep_fd=20= =3D=20-1;=0A+=20=20cb->eno=20=3D=20errno;=0A+=20=20return=20res;=0A+}=0A= +=0A=20int=0A=20scm_std_select=20(int=20nfds,=0A=20=09=09SELECT_TYPE=20= *readfds,=0A@@=20-1777,45=20+1832,41=20@@=20scm_std_select=20(int=20= nfds,=0A=20=09=09struct=20timeval=20*timeout)=0A=20{=0A=20=20=20fd_set=20= my_readfds;=0A-=20=20int=20res,=20eno,=20wakeup_fd;=0A+=20=20int=20res;=0A= =20=20=20scm_i_thread=20*t=20=3D=20SCM_I_CURRENT_THREAD;=0A-=20=20= scm_t_guile_ticket=20ticket;=0A+=20=20struct=20select_callback_data=20cb=20= =3D=20{=0A+=20=20=20=20readfds,=20writefds,=20exceptfds,=20timeout,=20t,=20= nfds,=0A+=20=20};=0A=20=0A=20=20=20if=20(readfds=20=3D=3D=20NULL)=0A=20=20= =20=20=20{=0A=20=20=20=20=20=20=20FD_ZERO=20(&my_readfds);=0A-=20=20=20=20= =20=20readfds=20=3D=20&my_readfds;=0A+=20=20=20=20=20=20cb.readfds=20=3D=20= &my_readfds;=0A=20=20=20=20=20}=0A=20=0A=20=20=20while=20= (scm_i_setup_sleep=20(t,=20SCM_BOOL_F,=20NULL,=20t->sleep_pipe[1]))=0A=20= =20=20=20=20SCM_TICK;=0A=20=0A-=20=20wakeup_fd=20=3D=20t->sleep_pipe[0];=0A= -=20=20ticket=20=3D=20scm_leave_guile=20();=0A-=20=20FD_SET=20= (wakeup_fd,=20readfds);=0A-=20=20if=20(wakeup_fd=20>=3D=20nfds)=0A-=20=20= =20=20nfds=20=3D=20wakeup_fd+1;=0A-=20=20res=20=3D=20select=20(nfds,=20= readfds,=20writefds,=20exceptfds,=20timeout);=0A-=20=20t->sleep_fd=20=3D=20= -1;=0A-=20=20eno=20=3D=20errno;=0A-=20=20scm_enter_guile=20(ticket);=0A+=20= =20cb.wakeup_fd=20=3D=20t->sleep_pipe[0];=0A+=0A+=20=20res=20=3D=20= scm_without_guile_int=20(select_callback,=20&cb);=0A=20=0A=20=20=20= scm_i_reset_sleep=20(t);=0A=20=0A-=20=20if=20(res=20>=200=20&&=20= FD_ISSET=20(wakeup_fd,=20readfds))=0A+=20=20if=20(res=20>=200=20&&=20= FD_ISSET=20(cb.wakeup_fd,=20cb.readfds))=0A=20=20=20=20=20{=0A=20=20=20=20= =20=20=20char=20dummy;=0A-=20=20=20=20=20=20full_read=20(wakeup_fd,=20= &dummy,=201);=0A+=20=20=20=20=20=20full_read=20(cb.wakeup_fd,=20&dummy,=20= 1);=0A=20=0A-=20=20=20=20=20=20FD_CLR=20(wakeup_fd,=20readfds);=0A+=20=20= =20=20=20=20FD_CLR=20(cb.wakeup_fd,=20cb.readfds);=0A=20=20=20=20=20=20=20= res=20-=3D=201;=0A=20=20=20=20=20=20=20if=20(res=20=3D=3D=200)=0A=20=09{=0A= -=09=20=20eno=20=3D=20EINTR;=0A+=09=20=20cb.eno=20=3D=20EINTR;=0A=20=09=20= =20res=20=3D=20-1;=0A=20=09}=0A=20=20=20=20=20}=0A-=20=20errno=20=3D=20= eno;=0A+=20=20errno=20=3D=20cb.eno;=0A=20=20=20return=20res;=0A=20}=0A=20= =0A@@=20-1823,18=20+1874,18=20@@=20scm_std_select=20(int=20nfds,=0A=20=0A= =20#if=20SCM_USE_PTHREAD_THREADS=0A=20=0A+static=20int=0A= +mutex_lock_callback=20(void=20*p)=0A+{=0A+=20=20return=20= scm_i_pthread_mutex_lock=20(p);=0A+}=0A+=0A=20int=0A=20= scm_pthread_mutex_lock=20(scm_i_pthread_mutex_t=20*mutex)=0A=20{=0A=20=20= =20if=20(scm_i_pthread_mutex_trylock=20(mutex)=20=3D=3D=200)=0A=20=20=20=20= =20return=200;=0A-=20=20else=0A-=20=20=20=20{=0A-=20=20=20=20=20=20= scm_t_guile_ticket=20t=20=3D=20scm_leave_guile=20();=0A-=20=20=20=20=20=20= int=20res=20=3D=20scm_i_pthread_mutex_lock=20(mutex);=0A-=20=20=20=20=20=20= scm_enter_guile=20(t);=0A-=20=20=20=20=20=20return=20res;=0A-=20=20=20=20= }=0A+=20=20return=20scm_without_guile_int=20(mutex_lock_callback,=20= mutex);=0A=20}=0A=20=0A=20static=20void=0A@@=20-1850,14=20+1901,45=20@@=20= scm_dynwind_pthread_mutex_lock=20(scm_i_pthread_mutex_t=20*mutex)=0A=20=20= =20scm_dynwind_unwind_handler=20(do_unlock,=20mutex,=20= SCM_F_WIND_EXPLICITLY);=0A=20}=0A=20=0A+struct=20cond_wait_callback_data=20= {=0A+=20=20scm_i_pthread_cond_t=20*cond;=0A+=20=20scm_i_pthread_mutex_t=20= *mutex;=0A+};=0A+=0A+static=20int=0A+cond_wait_callback=20(void=20*p)=0A= +{=0A+=20=20struct=20cond_wait_callback_data=20*cb=20=3D=20p;=0A+=20=20= int=20res;=0A+=20=20scm_i_thread=20*t=20=3D=20SCM_I_CURRENT_THREAD;=0A+=20= =20t->held_mutex=20=3D=20cb->mutex;=0A+=20=20res=20=3D=20= scm_i_pthread_cond_wait=20(cb->cond,=20cb->mutex);=0A+=20=20= t->held_mutex=20=3D=20NULL;=0A+=20=20return=20res;=0A+}=0A+=0A=20int=0A=20= scm_pthread_cond_wait=20(scm_i_pthread_cond_t=20*cond,=20= scm_i_pthread_mutex_t=20*mutex)=0A=20{=0A-=20=20scm_t_guile_ticket=20t=20= =3D=20scm_leave_guile=20();=0A-=20=20((scm_i_thread=20*)t)->held_mutex=20= =3D=20mutex;=0A-=20=20int=20res=20=3D=20scm_i_pthread_cond_wait=20(cond,=20= mutex);=0A-=20=20((scm_i_thread=20*)t)->held_mutex=20=3D=20NULL;=0A-=20=20= scm_enter_guile=20(t);=0A+=20=20struct=20cond_wait_callback_data=20cb=20= =3D=20{=20cond,=20mutex=20};=0A+=20=20return=20scm_without_guile_int=20= (cond_wait_callback,=20&cb);=0A+}=0A+=0A+struct=20= cond_timedwait_callback_data=20{=0A+=20=20scm_i_pthread_cond_t=20*cond;=0A= +=20=20scm_i_pthread_mutex_t=20*mutex;=0A+=20=20const=20scm_t_timespec=20= *wt;=0A+};=0A+=0A+static=20int=0A+cond_timedwait_callback=20(void=20*p)=0A= +{=0A+=20=20struct=20cond_timedwait_callback_data=20*cb=20=3D=20p;=0A+=20= =20int=20res;=0A+=20=20scm_i_thread=20*t=20=3D=20SCM_I_CURRENT_THREAD;=0A= +=20=20t->held_mutex=20=3D=20cb->mutex;=0A+=20=20res=20=3D=20= scm_i_pthread_cond_timedwait=20(cb->cond,=20cb->mutex,=20cb->wt);=0A+=20=20= t->held_mutex=20=3D=20NULL;=0A=20=20=20return=20res;=0A=20}=0A=20=0A@@=20= -1866,12=20+1948,8=20@@=20scm_pthread_cond_timedwait=20= (scm_i_pthread_cond_t=20*cond,=0A=20=09=09=09=20=20=20=20= scm_i_pthread_mutex_t=20*mutex,=0A=20=09=09=09=20=20=20=20const=20= scm_t_timespec=20*wt)=0A=20{=0A-=20=20scm_t_guile_ticket=20t=20=3D=20= scm_leave_guile=20();=0A-=20=20((scm_i_thread=20*)t)->held_mutex=20=3D=20= mutex;=0A-=20=20int=20res=20=3D=20scm_i_pthread_cond_timedwait=20(cond,=20= mutex,=20wt);=0A-=20=20((scm_i_thread=20*)t)->held_mutex=20=3D=20NULL;=0A= -=20=20scm_enter_guile=20(t);=0A-=20=20return=20res;=0A+=20=20struct=20= cond_timedwait_callback_data=20cb=20=3D=20{=20cond,=20mutex,=20wt=20};=0A= +=20=20return=20scm_without_guile_int=20(cond_timedwait_callback,=20= &cb);=0A=20}=0A=20=0A=20#endif=0A@@=20-1970,25=20+2048,6=20@@=20int=20= scm_i_thread_go_to_sleep;=0A=20static=20int=20threads_initialized_p=20=3D=20= 0;=0A=20=0A=20void=0A-scm_i_thread_put_to_sleep=20()=0A-{=0A-=20=20if=20= (threads_initialized_p)=0A-=20=20=20=20{=0A-=20=20=20=20=20=20= scm_i_thread=20*t;=0A-=0A-=20=20=20=20=20=20scm_leave_guile=20();=0A-=20=20= =20=20=20=20scm_i_pthread_mutex_lock=20(&thread_admin_mutex);=0A-=0A-=20=20= =20=20=20=20/*=20Signal=20all=20threads=20to=20go=20to=20sleep=0A-=20=20=20= =20=20=20=20*/=0A-=20=20=20=20=20=20scm_i_thread_go_to_sleep=20=3D=201;=0A= -=20=20=20=20=20=20for=20(t=20=3D=20all_threads;=20t;=20t=20=3D=20= t->next_thread)=0A-=09scm_i_pthread_mutex_lock=20(&t->heap_mutex);=0A-=20= =20=20=20=20=20scm_i_thread_go_to_sleep=20=3D=200;=0A-=20=20=20=20}=0A-}=0A= -=0A-void=0A=20scm_i_thread_invalidate_freelists=20()=0A=20{=0A=20=20=20= /*=20thread_admin_mutex=20is=20already=20locked.=20*/=0A@@=20-1999,34=20= +2058,68=20@@=20scm_i_thread_invalidate_freelists=20()=0A=20=20=20=20=20=20= =20t->clear_freelists_p=20=3D=201;=0A=20}=0A=20=0A+struct=20= sleeping_callback=20{=0A+=20=20void=20(*func)=20(void=20*);=0A+=20=20= void=20*data;=0A+};=0A+=0A+static=20void=20*=0A+sleeping_callback=20= (void=20*p)=0A+{=0A+=20=20struct=20sleeping_callback=20*cb=20=3D=20p;=0A= +=20=20scm_i_thread=20*t;=0A+=0A+=20=20scm_i_pthread_mutex_lock=20= (&thread_admin_mutex);=0A+=0A+=20=20/*=20Signal=20all=20threads=20to=20= go=20to=20sleep=0A+=20=20=20*/=0A+=20=20scm_i_thread_go_to_sleep=20=3D=20= 1;=0A+=20=20for=20(t=20=3D=20all_threads;=20t;=20t=20=3D=20= t->next_thread)=0A+=20=20=20=20scm_i_pthread_mutex_lock=20= (&t->heap_mutex);=0A+=20=20scm_i_thread_go_to_sleep=20=3D=200;=0A+=0A+=20= =20cb->func=20(cb->data);=0A+=0A+=20=20scm_i_pthread_cond_broadcast=20= (&wake_up_cond);=0A+=20=20for=20(t=20=3D=20all_threads;=20t;=20t=20=3D=20= t->next_thread)=0A+=20=20=20=20scm_i_pthread_mutex_unlock=20= (&t->heap_mutex);=0A+=20=20scm_i_pthread_mutex_unlock=20= (&thread_admin_mutex);=0A+=0A+=20=20return=20NULL;=0A+}=0A+=0A=20void=0A= -scm_i_thread_wake_up=20()=0A+scm_i_with_threads_sleeping=20(void=20= (*func)(void=20*),=20void=20*data)=0A=20{=0A=20=20=20if=20= (threads_initialized_p)=0A=20=20=20=20=20{=0A-=20=20=20=20=20=20= scm_i_thread=20*t;=0A-=0A-=20=20=20=20=20=20scm_i_pthread_cond_broadcast=20= (&wake_up_cond);=0A-=20=20=20=20=20=20for=20(t=20=3D=20all_threads;=20t;=20= t=20=3D=20t->next_thread)=0A-=09scm_i_pthread_mutex_unlock=20= (&t->heap_mutex);=0A-=20=20=20=20=20=20scm_i_pthread_mutex_unlock=20= (&thread_admin_mutex);=0A-=20=20=20=20=20=20scm_enter_guile=20= ((scm_t_guile_ticket)=20SCM_I_CURRENT_THREAD);=0A+=20=20=20=20=20=20= struct=20sleeping_callback=20cb=20=3D=20{=20func,=20data=20};=0A+=20=20=20= =20=20=20scm_without_guile=20(sleeping_callback,=20&cb);=0A+=20=20=20=20= }=0A+=20=20else=0A+=20=20=20=20{=0A+=20=20=20=20=20=20func=20(data);=0A+=20= =20=20=20=20=20/*=20Can=20func=20ever=20cause=20initialization=20to=20= happen=20if=20it=20hadn't=0A+=09=20been=20done=20before?=20=20*/=0A+=20=20= =20=20=20=20assert=20(threads_initialized_p=20=3D=3D=200);=0A=20=20=20=20= =20}=0A=20}=0A=20=0A-void=0A-scm_i_thread_sleep_for_gc=20()=0A+static=20= void=0A+sleep_for_gc_helper=20(void=20*p,=20scm_i_thread=20*t)=0A=20{=0A= -=20=20scm_i_thread=20*t=20=3D=20suspend=20();=0A-=0A=20=20=20/*=20Don't=20= put=20t->heap_mutex=20in=20t->held_mutex=20here,=20because=20if=20the=0A=20= =20=20=20=20=20thread=20is=20cancelled=20during=20the=20cond=20wait,=20= the=20thread's=20cleanup=0A=20=20=20=20=20=20function=20= (scm_leave_guile_cleanup)=20will=20handle=20unlocking=20the=0A=20=20=20=20= =20=20heap_mutex,=20so=20we=20don't=20need=20to=20do=20that=20again=20in=20= on_thread_exit.=0A=20=20=20*/=0A=20=20=20scm_i_pthread_cond_wait=20= (&wake_up_cond,=20&t->heap_mutex);=0A+}=0A=20=0A-=20=20resume=20(t);=0A= +void=0A+scm_i_thread_sleep_for_gc=20()=0A+{=0A+=20=20while_suspended=20= (sleep_for_gc_helper,=20NULL);=0A=20}=0A=20=0A=20/*=20This=20mutex=20is=20= used=20by=20SCM_CRITICAL_SECTION_START/END.=0Adiff=20--git=20= a/libguile/threads.h=20b/libguile/threads.h=0Aindex=2032b0ea6..407acb7=20= 100644=0A---=20a/libguile/threads.h=0A+++=20b/libguile/threads.h=0A@@=20= -153,8=20+153,8=20@@=20SCM_INTERNAL=20void=20= *scm_i_with_guile_and_parent=20(void=20*(*func)(void=20*),=0A=20=0A=20= extern=20int=20scm_i_thread_go_to_sleep;=0A=20=0A-SCM_INTERNAL=20void=20= scm_i_thread_put_to_sleep=20(void);=0A-SCM_INTERNAL=20void=20= scm_i_thread_wake_up=20(void);=0A+SCM_INTERNAL=20void=20= scm_i_with_threads_sleeping=20(void=20(*func)(void=20*),=0A+=09=09=09=09=09= =20=20=20=20=20=20=20void=20*data);=0A=20SCM_INTERNAL=20void=20= scm_i_thread_invalidate_freelists=20(void);=0A=20void=20= scm_i_thread_sleep_for_gc=20(void);=0A=20=0A= --Apple-Mail-66-686113847 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit --Apple-Mail-66-686113847--