This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: SCM_{DEFER,ALLOW}_INTS


forcer <forcer@mindless.com> writes:

> Hmm... i'm seriously confused about the use of
> SCM_{DEFER,ALLOW}_INTS. Since i couldn't find anything about them
> in the documentation i have here, i checked the guile sources,
> and found the following in unif.c:
> 
> SCM
> scm_makflo (float x)
> {
>   SCM z;
>   if (x == 0.0)
>     return scm_flo0;
>   SCM_NEWCELL (z);
>   SCM_DEFER_INTS;
>   SCM_SETCAR (z, scm_tc_flo);
>   SCM_FLO (z) = x;
>   SCM_ALLOW_INTS;
>   return z;
> }
> 
> That is, it creates a new cell with interrupts enabled, and then
> disables the interrupts and assigns values to the cell.
> Why were the interrupts disabled only after the cell was created?
> 
> And more important, where can i find more information about the
> *_INTS calls? Especially, what exactly they do and where one
> would need them.

You need them in places where, if an asynchronous event were to occur,
the program would be left in an inconsistent state; in that
particular example, if something else were to run between the
call to SCM_SETCAR & the setting of SCM_FLO to x, a gc might occur,
which would find a half-finished cell. These types of places really
should be removed, since it's easier and less confusing to just change
the assignments to go cdr first, and make the gc leave the cells
alone. 

I've done some documentation for this as part of documenting async.c
for the qdocs (but it's not finished yet). This is the section about
the ALLOW/DEFER macros, but I'm not sure how useful it actually is ;)

Topic: async execution control

C Macro: SCM_DEFER_INTS

Disables the running of asyncs until SCM_ALLOW_INTS. Also disallows
the running of other threads. [1]

C Macro: SCM_ALLOW_INTS

Allows asyncs and threads to run. [1] The actual sequence goes:

* Check if ints are already enabled.

* Check to see if there are any threads pending and if we're supposed
  to switch now (given by scm_switch_counter). The current thread
  yields if this is the case. This is implemented by a `call' to the
  macro SCM_THREAD_SWITCHING_CODE

* Start allowing other threads by calling SCM_THREAD_ALLOW. Currently
  this doesn't actually do anything, since guile's current set of
  threads are cooperative, so (I think) the call to
  SCM_THREAD_SWITCHING_CODE should handle it

* Do a SCM_ASYNC_TICK


C Macro: SCM_ALLOW_INTS_ONLY

Calls SCM_THREAD_ALLOW, and sets scm_ints_disabled to 0. Doesn't
actually cause anything to happen currently. [1]

C Macro: SCM_REDEFER_INTS

Intended to be called when ints are already disabled... this basically
just redefers threads and increments scm_ints_disabled.

C Macro: SCM_REALLOW_INTS

The end block for a SCM_REDEFER_INTS. This basically does the same
thing as SCM_ALLOW_INTS, but basically allows us to nest defer's and
allow's arbitrarily. This decrements scm_ints_disabled, and does the
normal ALLOW_INTS actions when scm_ints_disabled hit's 0.


> In a related context, is there anything special to note for
> guile-using C-code? I need to serialze access to functions of a
> library that's not thread-safe. Is it sufficient to use pthread
> mutex's here?

-- 
Greg