@@ -44,6 +44,7 @@ VM* init_vm(int stack_size, size_t heap_size,
4444 memset(vm->inbox, 0, 1024*sizeof(VAL));
4545 vm->inbox_end = vm->inbox + 1024;
4646 vm->inbox_write = vm->inbox;
47+ vm->inbox_nextid = 1;
4748
4849 // The allocation lock must be reentrant. The lock exists to ensure that
4950 // no memory is allocated during the message sending process, but we also
@@ -825,7 +826,7 @@ VAL copyTo(VM* vm, VAL x) {
825826}
826827
827828// Add a message to another VM's message queue
828−int idris_sendMessage(VM* sender, VM* dest, VAL msg) {
829+int idris_sendMessage(VM* sender, int channel_id, VM* dest, VAL msg) {
829830 // FIXME: If GC kicks in in the middle of the copy, we're in trouble.
830831 // Probably best check there is enough room in advance. (How?)
831832
@@ -861,6 +862,14 @@ int idris_sendMessage(VM* sender, VM* dest, VAL msg) {
861862 }
862863
863864 dest->inbox_write->msg = dmsg;
865+ if (channel_id == 0) {
866+ // Set lowest bit to indicate this message is initiating a channel
867+ channel_id = 1 + ((dest->inbox_nextid++) << 1);
868+ } else {
869+ channel_id = channel_id << 1;
870+ }
871+ dest->inbox_write->channel_id = channel_id;
872+
864873 dest->inbox_write->sender = sender;
865874 dest->inbox_write++;
866875
@@ -873,26 +882,39 @@ int idris_sendMessage(VM* sender, VM* dest, VAL msg) {
873882
874883 pthread_mutex_unlock(&(dest->inbox_lock));
875884// printf("Sending [unlock]...\n");
876− return 1;
885+ return channel_id >> 1;
877886}
878887
879888VM* idris_checkMessages(VM* vm) {
880− return idris_checkMessagesFrom(vm, NULL);
889+ return idris_checkMessagesFrom(vm, 0, NULL);
881890}
882891
883−VM* idris_checkMessagesFrom(VM* vm, VM* sender) {
892+Msg* idris_checkInitMessages(VM* vm) {
893+ Msg* msg;
894+
895+ for (msg = vm->inbox; msg < vm->inbox_end && msg->msg != NULL; ++msg) {
896+ if (msg->channel_id && 1 == 1) { // init bit set
897+ return msg;
898+ }
899+ }
900+ return 0;
901+}
902+
903+VM* idris_checkMessagesFrom(VM* vm, int channel_id, VM* sender) {
884904 Msg* msg;
885905
886906 for (msg = vm->inbox; msg < vm->inbox_end && msg->msg != NULL; ++msg) {
887907 if (sender == NULL || msg->sender == sender) {
888− return msg->sender;
908+ if (channel_id == 0 || channel_id == msg->channel_id >> 1) {
909+ return msg->sender;
910+ }
889911 }
890912 }
891913 return 0;
892914}
893915
894916VM* idris_checkMessagesTimeout(VM* vm, int delay) {
895− VM* sender = idris_checkMessagesFrom(vm, NULL);
917+ VM* sender = idris_checkMessagesFrom(vm, 0, NULL);
896918 if (sender != NULL) {
897919 return sender;
898920 }
@@ -910,16 +932,18 @@ VM* idris_checkMessagesTimeout(VM* vm, int delay) {
910932 (void)(status); //don't emit 'unused' warning
911933 pthread_mutex_unlock(&vm->inbox_block);
912934
913− return idris_checkMessagesFrom(vm, NULL);
935+ return idris_checkMessagesFrom(vm, 0, NULL);
914936}
915937
916938
917−Msg* idris_getMessageFrom(VM* vm, VM* sender) {
939+Msg* idris_getMessageFrom(VM* vm, int channel_id, VM* sender) {
918940 Msg* msg;
919941
920942 for (msg = vm->inbox; msg < vm->inbox_write; ++msg) {
921943 if (sender == NULL || msg->sender == sender) {
922− return msg;
944+ if (channel_id == 0 || channel_id == msg->channel_id >> 1) {
945+ return msg;
946+ }
923947 }
924948 }
925949 return NULL;
@@ -927,18 +951,20 @@ Msg* idris_getMessageFrom(VM* vm, VM* sender) {
927951
928952// block until there is a message in the queue
929953Msg* idris_recvMessage(VM* vm) {
930− return idris_recvMessageFrom(vm, NULL);
954+ return idris_recvMessageFrom(vm, 0, NULL);
931955}
932956
933−Msg* idris_recvMessageFrom(VM* vm, VM* sender) {
957+Msg* idris_recvMessageFrom(VM* vm, int channel_id, VM* sender) {
934958 Msg* msg;
935959 Msg* ret = malloc(sizeof(Msg));
936960
937961 struct timespec timeout;
938962 int status;
963+
964+ if (sender && sender->active == 0) { return NULL; } // No VM to receive from
939965
940966 pthread_mutex_lock(&vm->inbox_block);
941− msg = idris_getMessageFrom(vm, sender);
967+ msg = idris_getMessageFrom(vm, channel_id, sender);
942968
943969 while (msg == NULL) {
944970// printf("No message yet\n");
@@ -949,7 +975,7 @@ Msg* idris_recvMessageFrom(VM* vm, VM* sender) {
949975 &timeout);
950976 (void)(status); //don't emit 'unused' warning
951977// printf("Waiting [unlock]... %d\n", status);
952− msg = idris_getMessageFrom(vm, sender);
978+ msg = idris_getMessageFrom(vm, channel_id, sender);
953979 }
954980 pthread_mutex_unlock(&vm->inbox_block);
955981
@@ -993,6 +1019,10 @@ VM* idris_getSender(Msg* msg) {
9931019 return msg->sender;
9941020}
9951021
1022+int idris_getChannel(Msg* msg) {
1023+ return msg->channel_id >> 1;
1024+}
1025+
9961026void idris_freeMsg(Msg* msg) {
9971027 free(msg);
9981028}