diff --git a/driver/others/memory.c b/driver/others/memory.c index 8e24773841..eea073259e 100644 --- a/driver/others/memory.c +++ b/driver/others/memory.c @@ -2825,18 +2825,19 @@ void *blas_memory_alloc(int procpos){ position = 0; -#if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) - LOCK_COMMAND(&alloc_lock); -#endif + /* Slots of memory[] are claimed with their own lock rather than alloc_lock, + so that threads of the application calling OpenBLAS concurrently (e.g. + from an OpenMP parallel region) don't all take the same mutex twice per + call. */ do { RMB; -#if defined(USE_OPENMP) +#if defined(SMP) || defined(USE_LOCKING) if (!memory[position].used) { blas_lock((BLASULONG *)&memory[position].lock); #endif if (!memory[position].used) goto allocation; -#if defined(USE_OPENMP) +#if defined(SMP) || defined(USE_LOCKING) blas_unlock((BLASULONG *)&memory[position].lock); } #endif @@ -2844,6 +2845,9 @@ void *blas_memory_alloc(int procpos){ } while (position < NUM_BUFFERS); +#if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) + LOCK_COMMAND(&alloc_lock); +#endif if (memory_overflowed) { do { @@ -2874,9 +2878,7 @@ void *blas_memory_alloc(int procpos){ #endif memory[position].used = 1; -#if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) - UNLOCK_COMMAND(&alloc_lock); -#else +#if defined(SMP) || defined(USE_LOCKING) blas_unlock((BLASULONG *)&memory[position].lock); #endif if (!memory[position].addr) { @@ -2946,13 +2948,7 @@ void *blas_memory_alloc(int procpos){ } while ((BLASLONG)map_address == -1); -#if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) - LOCK_COMMAND(&alloc_lock); -#endif memory[position].addr = map_address; -#if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) - UNLOCK_COMMAND(&alloc_lock); -#endif #ifdef DEBUG printf(" Mapping Succeeded. %p(%d)\n", (void *)memory[position].addr, position); @@ -3127,48 +3123,46 @@ void blas_memory_free(void *free_area){ #endif position = 0; -#if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) - LOCK_COMMAND(&alloc_lock); -#endif + /* Only the thread holding a buffer of memory[] frees it, so its slot is + released without alloc_lock, as it is claimed in blas_memory_alloc. */ while ((position < NUM_BUFFERS) && (memory[position].addr != free_area)) position++; - if (position >= NUM_BUFFERS && !memory_overflowed) goto error; + if (likely(position < NUM_BUFFERS)) { +#ifdef DEBUG + printf(" Position : %d\n", position); +#endif + // arm: ensure all writes are finished before other thread takes this memory + WMB; + + memory[position].used = 0; #ifdef DEBUG - if (memory[position].addr != free_area) goto error; - printf(" Position : %d\n", position); + printf("Unmap Succeeded.\n\n"); #endif - if (unlikely(memory_overflowed && position >= NUM_BUFFERS)) { - while ((position < NUM_BUFFERS+NEW_BUFFERS) && (newmemory[position-NUM_BUFFERS].addr != free_area)) - position++; - // arm: ensure all writes are finished before other thread takes this memory - WMB; -if (position - NUM_BUFFERS >= NEW_BUFFERS) goto error; - newmemory[position-NUM_BUFFERS].used = 0; + return; + } + #if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) - UNLOCK_COMMAND(&alloc_lock); + LOCK_COMMAND(&alloc_lock); #endif + if (!memory_overflowed) goto error; -#ifdef DEBUG - printf("Unmap from overflow area succeeded.\n\n"); -#endif - return; -} else { + while ((position < NUM_BUFFERS+NEW_BUFFERS) && (newmemory[position-NUM_BUFFERS].addr != free_area)) + position++; // arm: ensure all writes are finished before other thread takes this memory WMB; - - memory[position].used = 0; + if (position - NUM_BUFFERS >= NEW_BUFFERS) goto error; + newmemory[position-NUM_BUFFERS].used = 0; #if (defined(SMP) || defined(USE_LOCKING)) && !defined(USE_OPENMP) UNLOCK_COMMAND(&alloc_lock); #endif #ifdef DEBUG - printf("Unmap Succeeded.\n\n"); + printf("Unmap from overflow area succeeded.\n\n"); #endif - return; -} + error: printf("BLAS : Bad memory unallocation! : %4d %p\n", position, free_area);