--- old/./README.md	2013-02-04 22:11:13.337740065 +0000
+++ new/./README.md	2013-02-04 22:11:13.343227302 +0000
@@ -563,7 +563,7 @@
 		 * v8plus_jsfunc_hold()
 		 * v8plus_jsfunc_rele()
 		 * v8plus_call()
-		 * v8plus_method_call()
+		 * v8plus_method_call_direct()
 		 * v8plus_defer()
 		 *
 		 * If you touch anything inside op, you may need locking to
@@ -651,12 +651,11 @@
 	util.inherits(MyObjectWrapper, events.EventEmitter);
 
 Then, in C code, you must arrange for libuv to call a C function in the
-context of the main event loop.  How to do this depends on what type of
-asynchronous event you are waiting for; for example, the `uv_poll` mechanism
-will call you back in the appropriate context when a file descriptor becomes
-readable or writable.  Because libuv is a C library, you can easily use
-these interfaces directly in your v8+ addon.  Your libuv callback might then
-contain code looking something like this:
+context of the main event loop.  The function `v8plus_method_call()` is safe
+to call from any thread: depending on the context in which it is invoked, it
+will either make the call directly or queue the call in the main event loop
+and block on a reply.  Simply arrange to call back into your JavaScript
+object when you wish to post an event:
 
 	nvlist_t *eap;
 	nvlist_t *erp;
@@ -728,6 +727,13 @@
 emitter example above.  The effects of using this function to call a native
 method are undefined.
 
+As JavaScript functions must be called from the event loop thread,
+`v8plus_method_call()` contains logic to determine whether we are in the
+correct context or not.  If we are running on some other thread we will
+queue the request and sleep, waiting for the event loop thread to make the
+call.  In the simple case, where we are already in the correct thread, we
+make the call directly.
+
 ## FAQ
 
 - Why?
--- old/examples/example.h	2013-02-04 22:11:13.471823000 +0000
+++ new/examples/example.h	2013-02-04 22:11:13.477224586 +0000
@@ -12,8 +12,6 @@
 extern "C" {
 #endif	/* __cplusplus */
 
-#define	__UNUSED	__attribute__((__unused__))
-
 typedef struct example {
 	uint64_t e_val;
 } example_t;
--- old/./v8plus_csup.c	2013-02-04 22:11:13.587635598 +0000
+++ new/./v8plus_csup.c	2013-02-04 22:11:13.593029637 +0000
@@ -45,8 +45,6 @@
 	STAILQ_ENTRY(v8plus_async_call) vac_callq_entry;
 } v8plus_async_call_t;
 
-nvlist_t *v8plus_method_call_direct(void *, const char *, const nvlist_t *);
-
 boolean_t
 v8plus_in_event_thread(void)
 {
@@ -54,7 +52,7 @@
 }
 
 static void
-v8plus_async_callback(uv_async_t *async, __attribute__((unused)) int status)
+v8plus_async_callback(uv_async_t *async, int status __UNUSED)
 {
 	if (v8plus_in_event_thread() != B_TRUE)
 		v8plus_panic("async callback called outside of event loop");
@@ -80,16 +78,14 @@
 		/*
 		 * Run the queued method:
 		 */
-		if (pthread_mutex_lock(&vac->vac_mtx) != 0)
-			v8plus_panic("could not lock async call mutex");
-
 		if (vac->vac_run == B_TRUE)
 			v8plus_panic("async call already run");
-
 		vac->vac_return = v8plus_method_call_direct(vac->vac_cop,
 		    vac->vac_name, vac->vac_lp);
-		vac->vac_run = B_TRUE;
 
+		if (pthread_mutex_lock(&vac->vac_mtx) != 0)
+			v8plus_panic("could not lock async call mutex");
+		vac->vac_run = B_TRUE;
 		if (pthread_cond_broadcast(&vac->vac_cv) != 0)
 			v8plus_panic("could not signal async call condvar");
 		if (pthread_mutex_unlock(&vac->vac_mtx) != 0)
@@ -117,6 +113,7 @@
 	 * condition variable until the event loop thread makes the call
 	 * for us and wakes us up.
 	 */
+	bzero(&vac, sizeof (vac));
 	vac.vac_cop = cop;
 	vac.vac_name = name;
 	vac.vac_lp = lp;
@@ -125,7 +122,6 @@
 	if (pthread_cond_init(&vac.vac_cv, NULL) != 0)
 		v8plus_panic("could not init async call condvar");
 	vac.vac_run = B_FALSE;
-	vac.vac_return = NULL;
 
 	/*
 	 * Post request to queue:
@@ -138,7 +134,7 @@
 	uv_async_send(&_v8plus_uv_async);
 
 	/*
-	 * Wait for our request to be serviced on the Event Loop thread:
+	 * Wait for our request to be serviced on the event loop thread:
 	 */
 	if (pthread_mutex_lock(&vac.vac_mtx) != 0)
 		v8plus_panic("could not lock async call mutex");
@@ -146,6 +142,13 @@
 		if (pthread_cond_wait(&vac.vac_cv, &vac.vac_mtx) != 0)
 			v8plus_panic("could not wait on async call condvar");
 	}
+	if (pthread_mutex_unlock(&vac.vac_mtx) != 0)
+		v8plus_panic("could not unlock async call mutex");
+
+	if (pthread_cond_destroy(&vac.vac_cv) != 0)
+		v8plus_panic("could not destroy async call condvar");
+	if (pthread_mutex_destroy(&vac.vac_mtx) != 0)
+		v8plus_panic("could not destroy async call mutex");
 
 	return (vac.vac_return);
 }
@@ -154,7 +157,7 @@
 /*
  * Initialise structures for off-event-loop method calls.
  *
- * Note that uv_async_init() must be called inside the libuv Event Loop, so we
+ * Note that uv_async_init() must be called inside the libuv event loop, so we
  * do it here.  We also want to record the thread ID of the Event Loop thread
  * so as to determine what kind of method calls to make later.
  */
--- old/./v8plus_glue.h	2013-02-04 22:11:13.717660252 +0000
+++ new/./v8plus_glue.h	2013-02-04 22:11:13.723062793 +0000
@@ -13,6 +13,8 @@
 extern "C" {
 #endif	/* __cplusplus */
 
+#define	__UNUSED	__attribute__((__unused__))
+
 #define	V8PLUS_ARG_F_NOEXTRA	0x01
 
 #define	V8PLUS_ERRMSG_LEN	512
@@ -163,10 +165,20 @@
  * results of calling a method implemented in C via this interface are
  * undefined.
  *
- * This can be used in concert with JS code to emit events asynchronously;
- * see the documentation.
+ * These methods can be used in concert with JS code to emit events
+ * asynchronously; see the documentation.
+ *
+ * Note: As JavaScript functions must be called from the event loop thread,
+ * v8plus_method_call() contains logic to determine whether we are in the
+ * correct context or not.  If we are running on some other thread we will
+ * queue the request and sleep, waiting for the event loop thread to make the
+ * call.  In the simple case, where we are already in the correct thread,
+ * we make the call directly.  v8plus_method_call_direct() assumes we are
+ * on the correct thread and always makes the call directly.
  */
 extern nvlist_t *v8plus_method_call(void *, const char *, const nvlist_t *);
+extern nvlist_t *v8plus_method_call_direct(void *, const char *,
+    const nvlist_t *);
 
 /*
  * These methods are analogous to strerror(3c) and similar functions; they
@@ -192,6 +204,12 @@
 extern const v8plus_static_descr_t v8plus_static_methods[];
 extern const uint_t v8plus_static_method_count;
 
+/*
+ * Private methods.
+ */
+extern boolean_t v8plus_in_event_thread(void);
+extern void v8plus_crossthread_init(void);
+
 #ifdef	__cplusplus
 }
 #endif	/* __cplusplus */
