OpenBLAS/driver/level3/level3_thread_lock.c

125 lines
3.9 KiB
C

/*********************************************************************/
/* Copyright 2026 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
/* without modification, are permitted provided that the following */
/* conditions are met: */
/* */
/* 1. Redistributions of source code must retain the above */
/* copyright notice, this list of conditions and the following */
/* disclaimer. */
/* */
/* 2. Redistributions in binary form must reproduce the above */
/* copyright notice, this list of conditions and the following */
/* disclaimer in the documentation and/or other materials */
/* provided with the distribution. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE OPENBLAS PROJECT ``AS IS'' */
/* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND */
/* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT */
/* SHALL THE OPENBLAS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY */
/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */
/* CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF */
/* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH */
/* DAMAGE. */
/* */
/*********************************************************************/
#include "common.h"
#ifdef USE_OPENMP
static omp_lock_t level3_lock, critical_section_lock;
static volatile BLASULONG init_lock = 0;
static _Atomic BLASULONG omp_lock_initialized = 0;
static volatile BLASULONG parallel_section_left = MAX_PARALLEL_NUMBER;
static void blas_level3_thread_lock_init(void)
{
while (omp_lock_initialized == 0) {
blas_lock(&init_lock);
if (omp_lock_initialized == 0) {
omp_init_lock(&level3_lock);
omp_init_lock(&critical_section_lock);
WMB;
omp_lock_initialized = 1;
}
blas_unlock(&init_lock);
}
}
void blas_level3_thread_enter(void)
{
blas_level3_thread_lock_init();
omp_set_lock(&level3_lock);
omp_set_lock(&critical_section_lock);
parallel_section_left--;
if (parallel_section_left != 0)
omp_unset_lock(&level3_lock);
omp_unset_lock(&critical_section_lock);
}
void blas_level3_thread_leave(void)
{
omp_set_lock(&critical_section_lock);
parallel_section_left++;
if (parallel_section_left == 1)
omp_unset_lock(&level3_lock);
omp_unset_lock(&critical_section_lock);
}
#elif defined(OS_WINDOWS)
static CRITICAL_SECTION level3_lock;
static volatile BLASULONG init_lock = 0;
static volatile BLASULONG level3_lock_initialized = 0;
static void blas_level3_thread_lock_init(void)
{
while (level3_lock_initialized == 0) {
blas_lock(&init_lock);
if (level3_lock_initialized == 0) {
InitializeCriticalSection((PCRITICAL_SECTION)&level3_lock);
WMB;
level3_lock_initialized = 1;
}
blas_unlock(&init_lock);
}
}
void blas_level3_thread_enter(void)
{
blas_level3_thread_lock_init();
EnterCriticalSection((PCRITICAL_SECTION)&level3_lock);
}
void blas_level3_thread_leave(void)
{
LeaveCriticalSection((PCRITICAL_SECTION)&level3_lock);
}
#else
static pthread_mutex_t level3_lock = PTHREAD_MUTEX_INITIALIZER;
void blas_level3_thread_enter(void)
{
pthread_mutex_lock(&level3_lock);
}
void blas_level3_thread_leave(void)
{
pthread_mutex_unlock(&level3_lock);
}
#endif