@@ -44,6 +44,7 @@ VM* init_vm(int stack_size, size_t heap_size,
44 memset(vm->inbox, 0, 1024*sizeof(VAL));
44 memset(vm->inbox, 0, 1024*sizeof(VAL));
45 vm->inbox_end = vm->inbox + 1024;
45 vm->inbox_end = vm->inbox + 1024;
46 vm->inbox_write = vm->inbox;
46 vm->inbox_write = vm->inbox;
47+ vm->inbox_nextid = 1;
48 // The allocation lock must be reentrant. The lock exists to ensure that
49 // The allocation lock must be reentrant. The lock exists to ensure that
49 // no memory is allocated during the message sending process, but we also
50 // no memory is allocated during the message sending process, but we also
@@ -825,7 +826,7 @@ VAL copyTo(VM* vm, VAL x) {
827// Add a message to another VM's message queue
828// 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) {
829 // FIXME: If GC kicks in in the middle of the copy, we're in trouble.
830 // FIXME: If GC kicks in in the middle of the copy, we're in trouble.
830 // Probably best check there is enough room in advance. (How?)
831 // Probably best check there is enough room in advance. (How?)
@@ -861,6 +862,14 @@ int idris_sendMessage(VM* sender, VM* dest, VAL msg) {
863 dest->inbox_write->msg = dmsg;
864 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);
869+ channel_id = channel_id << 1;
871+ dest->inbox_write->channel_id = channel_id;
864 dest->inbox_write->sender = sender;
873 dest->inbox_write->sender = sender;
865 dest->inbox_write++;
874 dest->inbox_write++;
@@ -873,26 +882,39 @@ int idris_sendMessage(VM* sender, VM* dest, VAL msg) {
874 pthread_mutex_unlock(&(dest->inbox_lock));
883 pthread_mutex_unlock(&(dest->inbox_lock));
875// printf("Sending [unlock]...\n");
884// printf("Sending [unlock]...\n");
876− return 1;
885+ return channel_id >> 1;
879VM* idris_checkMessages(VM* vm) {
888VM* idris_checkMessages(VM* vm) {
880− return idris_checkMessagesFrom(vm, NULL);
889+ return idris_checkMessagesFrom(vm, 0, NULL);
892+Msg* idris_checkInitMessages(VM* vm) {
895+ for (msg = vm->inbox; msg < vm->inbox_end && msg->msg != NULL; ++msg) {
896+ if (msg->channel_id && 1 == 1) { // init bit set
883−VM* idris_checkMessagesFrom(VM* vm, VM* sender) {
903+VM* idris_checkMessagesFrom(VM* vm, int channel_id, VM* sender) {
884 Msg* msg;
904 Msg* msg;
886 for (msg = vm->inbox; msg < vm->inbox_end && msg->msg != NULL; ++msg) {
906 for (msg = vm->inbox; msg < vm->inbox_end && msg->msg != NULL; ++msg) {
887 if (sender == NULL || msg->sender == sender) {
907 if (sender == NULL || msg->sender == sender) {
908+ if (channel_id == 0 || channel_id == msg->channel_id >> 1) {
888− return msg->sender;
909+ return msg->sender;
891 return 0;
913 return 0;
894VM* idris_checkMessagesTimeout(VM* vm, int delay) {
916VM* idris_checkMessagesTimeout(VM* vm, int delay) {
895− VM* sender = idris_checkMessagesFrom(vm, NULL);
917+ VM* sender = idris_checkMessagesFrom(vm, 0, NULL);
896 if (sender != NULL) {
918 if (sender != NULL) {
897 return sender;
919 return sender;
@@ -910,16 +932,18 @@ VM* idris_checkMessagesTimeout(VM* vm, int delay) {
910 (void)(status); //don't emit 'unused' warning
932 (void)(status); //don't emit 'unused' warning
911 pthread_mutex_unlock(&vm->inbox_block);
933 pthread_mutex_unlock(&vm->inbox_block);
913− return idris_checkMessagesFrom(vm, NULL);
935+ return idris_checkMessagesFrom(vm, 0, NULL);
917−Msg* idris_getMessageFrom(VM* vm, VM* sender) {
939+Msg* idris_getMessageFrom(VM* vm, int channel_id, VM* sender) {
918 Msg* msg;
940 Msg* msg;
920 for (msg = vm->inbox; msg < vm->inbox_write; ++msg) {
942 for (msg = vm->inbox; msg < vm->inbox_write; ++msg) {
921 if (sender == NULL || msg->sender == sender) {
943 if (sender == NULL || msg->sender == sender) {
944+ if (channel_id == 0 || channel_id == msg->channel_id >> 1) {
922− return msg;
945+ return msg;
925 return NULL;
949 return NULL;
@@ -927,18 +951,20 @@ Msg* idris_getMessageFrom(VM* vm, VM* sender) {
928// block until there is a message in the queue
952// block until there is a message in the queue
929Msg* idris_recvMessage(VM* vm) {
953Msg* idris_recvMessage(VM* vm) {
930− return idris_recvMessageFrom(vm, NULL);
954+ return idris_recvMessageFrom(vm, 0, NULL);
933−Msg* idris_recvMessageFrom(VM* vm, VM* sender) {
957+Msg* idris_recvMessageFrom(VM* vm, int channel_id, VM* sender) {
934 Msg* msg;
958 Msg* msg;
935 Msg* ret = malloc(sizeof(Msg));
959 Msg* ret = malloc(sizeof(Msg));
937 struct timespec timeout;
961 struct timespec timeout;
938 int status;
962 int status;
964+ if (sender && sender->active == 0) { return NULL; } // No VM to receive from
940 pthread_mutex_lock(&vm->inbox_block);
966 pthread_mutex_lock(&vm->inbox_block);
941− msg = idris_getMessageFrom(vm, sender);
967+ msg = idris_getMessageFrom(vm, channel_id, sender);
943 while (msg == NULL) {
969 while (msg == NULL) {
944// printf("No message yet\n");
970// printf("No message yet\n");
@@ -949,7 +975,7 @@ Msg* idris_recvMessageFrom(VM* vm, VM* sender) {
949 &timeout);
975 &timeout);
950 (void)(status); //don't emit 'unused' warning
976 (void)(status); //don't emit 'unused' warning
951// printf("Waiting [unlock]... %d\n", status);
977// printf("Waiting [unlock]... %d\n", status);
952− msg = idris_getMessageFrom(vm, sender);
978+ msg = idris_getMessageFrom(vm, channel_id, sender);
954 pthread_mutex_unlock(&vm->inbox_block);
980 pthread_mutex_unlock(&vm->inbox_block);
@@ -993,6 +1019,10 @@ VM* idris_getSender(Msg* msg) {
993 return msg->sender;
1019 return msg->sender;
1022+int idris_getChannel(Msg* msg) {
1023+ return msg->channel_id >> 1;
996void idris_freeMsg(Msg* msg) {
1026void idris_freeMsg(Msg* msg) {
997 free(msg);
1027 free(msg);