@@ -44,7 +44,6 @@ VM* init_vm(int stack_size, size_t heap_size,
44 vm->inbox = malloc(1024*sizeof(VAL));
44 vm->inbox = malloc(1024*sizeof(VAL));
45 memset(vm->inbox, 0, 1024*sizeof(VAL));
45 memset(vm->inbox, 0, 1024*sizeof(VAL));
46 vm->inbox_end = vm->inbox + 1024;
46 vm->inbox_end = vm->inbox + 1024;
47− vm->inbox_ptr = vm->inbox;
48 vm->inbox_write = vm->inbox;
47 vm->inbox_write = vm->inbox;
50 // 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
@@ -1096,18 +1095,19 @@ void idris_sendMessage(VM* sender, VM* dest, VAL msg) {
1098 pthread_mutex_lock(&(dest->inbox_lock));
1097 pthread_mutex_lock(&(dest->inbox_lock));
1099− *(dest->inbox_write) = dmsg;
1098+
1101− dest->inbox_write++;
1102 if (dest->inbox_write >= dest->inbox_end) {
1099 if (dest->inbox_write >= dest->inbox_end) {
1103− dest->inbox_write = dest->inbox;
1100+ // FIXME: This is obviously bad in the long run. This should
1104− }
1101+ // either block, make the inbox bigger, or return an error code,
1105−
1102+ // or possibly make it user configurable
1106− if (dest->inbox_write == dest->inbox_ptr) {
1107− fprintf(stderr, "Inbox full"); // Maybe grow it instead...
1103+ fprintf(stderr, "Inbox full");
1108 exit(-1);
1104 exit(-1);
1107+ dest->inbox_write->msg = dmsg;
1108+ dest->inbox_write->sender = sender;
1109+ dest->inbox_write++;
1111 // Wake up the other thread
1111 // Wake up the other thread
1112 pthread_mutex_lock(&dest->inbox_block);
1112 pthread_mutex_lock(&dest->inbox_block);
1113 pthread_cond_signal(&dest->inbox_waiting);
1113 pthread_cond_signal(&dest->inbox_waiting);
@@ -1120,18 +1120,46 @@ void idris_sendMessage(VM* sender, VM* dest, VAL msg) {
1122int idris_checkMessages(VM* vm) {
1122int idris_checkMessages(VM* vm) {
1123− VAL msg = *(vm->inbox_ptr);
1123+ return idris_checkMessagesFrom(vm, NULL);
1124− return (msg != NULL);
1124+}
1126+int idris_checkMessagesFrom(VM* vm, VM* sender) {
1129+ for (msg = vm->inbox; msg < vm->inbox_end && msg->msg != NULL; ++msg) {
1130+ if (sender == NULL || msg->sender == sender) {
1137+Msg* idris_getMessageFrom(VM* vm, VM* sender) {
1140+ for (msg = vm->inbox; msg < vm->inbox_write; ++msg) {
1141+ if (sender == NULL || msg->sender == sender) {
1127// block until there is a message in the queue
1148// block until there is a message in the queue
1128−VAL idris_recvMessage(VM* vm) {
1149+Msg* idris_recvMessage(VM* vm) {
1150+ return idris_recvMessageFrom(vm, NULL);
1153+Msg* idris_recvMessageFrom(VM* vm, VM* sender) {
1129− VAL msg;
1154+ Msg* msg;
1155+ Msg* ret = malloc(sizeof(Msg));
1130 struct timespec timeout;
1157 struct timespec timeout;
1131 int status;
1158 int status;
1133 pthread_mutex_lock(&vm->inbox_block);
1160 pthread_mutex_lock(&vm->inbox_block);
1134− msg = *(vm->inbox_ptr);
1161+ msg = idris_getMessageFrom(vm, sender);
1135 while (msg == NULL) {
1163 while (msg == NULL) {
1136// printf("No message yet\n");
1164// printf("No message yet\n");
1137// printf("Waiting [lock]...\n");
1165// printf("Waiting [lock]...\n");
@@ -1141,27 +1169,54 @@ VAL idris_recvMessage(VM* vm) {
1141 &timeout);
1169 &timeout);
1142 (void)(status); //don't emit 'unused' warning
1170 (void)(status); //don't emit 'unused' warning
1143// printf("Waiting [unlock]... %d\n", status);
1171// printf("Waiting [unlock]... %d\n", status);
1144− msg = *(vm->inbox_ptr);
1172+ msg = idris_getMessageFrom(vm, sender);
1146 pthread_mutex_unlock(&vm->inbox_block);
1174 pthread_mutex_unlock(&vm->inbox_block);
1148 if (msg != NULL) {
1176 if (msg != NULL) {
1177+ ret->msg = msg->msg;
1178+ ret->sender = msg->sender;
1149 pthread_mutex_lock(&(vm->inbox_lock));
1180 pthread_mutex_lock(&(vm->inbox_lock));
1150− *(vm->inbox_ptr) = NULL;
1181+
1151− vm->inbox_ptr++;
1182+ // Slide everything down after the message in the inbox,
1183+ // Move the inbox_write pointer down, and clear the value at the
1184+ // end - O(n) but it's easier since the message from a specific
1185+ // sender could be anywhere in the inbox
1187+ for(;msg < vm->inbox_write; ++msg) {
1152− if (vm->inbox_ptr >= vm->inbox_end) {
1188+ if (msg+1 != vm->inbox_end) {
1153− vm->inbox_ptr = vm->inbox;
1189+ msg->sender = (msg + 1)->sender;
1190+ msg->msg = (msg + 1)->msg;
1194+ vm->inbox_write->msg = NULL;
1195+ vm->inbox_write->sender = NULL;
1155 pthread_mutex_unlock(&(vm->inbox_lock));
1198 pthread_mutex_unlock(&(vm->inbox_lock));
1156 } else {
1199 } else {
1157 fprintf(stderr, "No messages waiting");
1200 fprintf(stderr, "No messages waiting");
1158 exit(-1);
1201 exit(-1);
1161− return msg;
1204+ return ret;
1208+VAL idris_getMsg(Msg* msg) {
1212+VM* idris_getSender(Msg* msg) {
1213+ return msg->sender;
1216+void idris_freeMsg(Msg* msg) {
1165VAL* nullary_cons;
1220VAL* nullary_cons;
1167void init_nullaries() {
1222void init_nullaries() {