on master help sign in
Merge pull request #1016 from SimonJF/rts-deadlock-fix

Fix deadlock in RTS when using allocation in native code

commit7d09d054f3f384a45f721fecce443327ef27be27 authorEdwin Brady <edwin.brady@gmail.com> dateTue 1 Apr 2014, 14:12 (13 years ago) parenta93acd6aa91121
1 file changed+12−3
rts/idris_rts.c+12−3
rts/idris_rts.c+12−3
@@ -37,9 +37,18 @@ VM* init_vm(int stack_size, size_t heap_size,
3737 vm->inbox_ptr = vm->inbox;
3838 vm->inbox_write = vm->inbox;
3939
40+ // The allocation lock must be reentrant. The lock exists to ensure that
41+ // no memory is allocated during the message sending process, but we also
42+ // check the lock in calls to allocate.
43+ // The problem comes when we use requireAlloc to guarantee a chunk of memory
44+ // first: this sets the lock, and since it is not reentrant, we get a deadlock.
45+ pthread_mutexattr_t rec_attr;
46+ pthread_mutexattr_init(&rec_attr);
47+ pthread_mutexattr_settype(&rec_attr, PTHREAD_MUTEX_RECURSIVE);
48+
4049 pthread_mutex_init(&(vm->inbox_lock), NULL);
4150 pthread_mutex_init(&(vm->inbox_block), NULL);
42− pthread_mutex_init(&(vm->alloc_lock), NULL);
51+ pthread_mutex_init(&(vm->alloc_lock), &rec_attr);
4352 pthread_cond_init(&(vm->inbox_waiting), NULL);
4453
4554 vm->max_threads = max_threads;
@@ -72,14 +81,14 @@ void idris_requireAlloc(VM* vm, size_t size) {
7281 }
7382
7483 int lock = vm->processes > 0;
75− if (lock) { // not message passing
84+ if (lock) { // We only need to lock if we're in concurrent mode
7685 pthread_mutex_lock(&vm->alloc_lock);
7786 }
7887}
7988
8089void idris_doneAlloc(VM* vm) {
8190 int lock = vm->processes > 0;
82− if (lock) { // not message passing
91+ if (lock) { // We only need to lock if we're in concurrent mode
8392 pthread_mutex_unlock(&vm->alloc_lock);
8493 }
8594}