+FN_(tryPutMVarzh_fast)
+{
+ StgMVar *mvar;
+ const StgInfoTable *info;
+
+ FB_
+ /* args: R1 = MVar, R2 = value */
+
+ mvar = (StgMVar *)R1.p;
+
+#ifdef SMP
+ info = LOCK_CLOSURE(mvar);
+#else
+ info = GET_INFO(mvar);
+#endif
+
+ if (info == &stg_FULL_MVAR_info) {
+
+#ifdef SMP
+ /* unlock the MVar */
+ mvar->header.info = &stg_FULL_MVAR_info;
+#endif
+
+ RET_N(0);
+ }
+
+ if (mvar->head != (StgTSO *)&stg_END_TSO_QUEUE_closure) {
+ /* There are takeMVar(s) waiting: wake up the first one
+ */
+ ASSERT(mvar->head->why_blocked == BlockedOnMVar);
+
+ /* actually perform the takeMVar */
+ PerformTake(mvar->head, R2.cl);
+
+#if defined(GRAN) || defined(PAR)
+ /* ToDo: check 2nd arg (mvar) is right */
+ mvar->head = RET_STGCALL2(StgTSO *,unblockOne,mvar->head,mvar);
+#else
+ mvar->head = RET_STGCALL1(StgTSO *,unblockOne,mvar->head);
+#endif
+ if (mvar->head == (StgTSO *)&stg_END_TSO_QUEUE_closure) {
+ mvar->tail = (StgTSO *)&stg_END_TSO_QUEUE_closure;
+ }
+#ifdef SMP
+ /* unlocks the MVar in the SMP case */
+ SET_INFO(mvar,&stg_EMPTY_MVAR_info);
+#endif
+ JMP_(ENTRY_CODE(Sp[0]));
+ } else {
+ /* No further takes, the MVar is now full. */
+ mvar->value = R2.cl;
+ /* unlocks the MVar in the SMP case */
+ SET_INFO(mvar,&stg_FULL_MVAR_info);
+ JMP_(ENTRY_CODE(Sp[0]));
+ }
+
+ /* ToDo: yield afterward for better communication performance? */