mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-13 09:58:54 +00:00
229 lines
5.7 KiB
C
229 lines
5.7 KiB
C
#if defined(SQLITE_MUTEX_RTTHREAD)
|
|
|
|
/*
|
|
* rt-thread mutex
|
|
*/
|
|
struct sqlite3_mutex {
|
|
struct rt_mutex mutex; /* Mutex controlling the lock */
|
|
int id; /* Mutex type */
|
|
};
|
|
|
|
SQLITE_PRIVATE void sqlite3MemoryBarrier(void)
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
** Initialize and deinitialize the mutex subsystem.
|
|
The argument to sqlite3_mutex_alloc() must one of these integer constants:
|
|
SQLITE_MUTEX_FAST
|
|
SQLITE_MUTEX_RECURSIVE
|
|
SQLITE_MUTEX_STATIC_MASTER
|
|
SQLITE_MUTEX_STATIC_MEM
|
|
SQLITE_MUTEX_STATIC_OPEN
|
|
SQLITE_MUTEX_STATIC_PRNG
|
|
SQLITE_MUTEX_STATIC_LRU
|
|
SQLITE_MUTEX_STATIC_PMEM
|
|
SQLITE_MUTEX_STATIC_APP1
|
|
SQLITE_MUTEX_STATIC_APP2
|
|
SQLITE_MUTEX_STATIC_APP3
|
|
SQLITE_MUTEX_STATIC_VFS1
|
|
SQLITE_MUTEX_STATIC_VFS2
|
|
SQLITE_MUTEX_STATIC_VFS3
|
|
The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
|
|
cause sqlite3_mutex_alloc() to create a new mutex. The new mutex is recursive
|
|
when SQLITE_MUTEX_RECURSIVE is used but not necessarily so when SQLITE_MUTEX_FAST
|
|
is used. The mutex implementation does not need to make a distinction between
|
|
SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does not want to.
|
|
SQLite will only request a recursive mutex in cases where it really needs one.
|
|
If a faster non-recursive mutex implementation is available on the host platform,
|
|
the mutex subsystem might return such a mutex in response to SQLITE_MUTEX_FAST.
|
|
|
|
The other allowed parameters to sqlite3_mutex_alloc()
|
|
(anything other than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
|
|
a pointer to a static preexisting mutex. Nine static mutexes are used by the
|
|
current version of SQLite. Future versions of SQLite may add additional static
|
|
mutexes. Static mutexes are for internal use by SQLite only. Applications that
|
|
use SQLite mutexes should use only the dynamic mutexes returned by SQLITE_MUTEX_FAST
|
|
or SQLITE_MUTEX_RECURSIVE.
|
|
|
|
Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST or SQLITE_MUTEX_RECURSIVE)
|
|
is used then sqlite3_mutex_alloc() returns a different mutex on every call.
|
|
For the static mutex types, the same mutex is returned on every call that has the same type number.
|
|
|
|
*/
|
|
static sqlite3_mutex _static_mutex[12];
|
|
|
|
static int _rtthread_mtx_init(void)
|
|
{
|
|
int i;
|
|
rt_err_t err;
|
|
|
|
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
|
|
{
|
|
err = rt_mutex_init(&_static_mutex[i].mutex, "sqlmtx", RT_IPC_FLAG_PRIO);
|
|
|
|
if (err != RT_EOK)
|
|
{
|
|
return SQLITE_ERROR;
|
|
}
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int _rtthread_mtx_end(void)
|
|
{
|
|
int i;
|
|
rt_err_t err;
|
|
|
|
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
|
|
{
|
|
err = rt_mutex_detach(&_static_mutex[i].mutex);
|
|
_static_mutex[i].mutex.owner = 0;
|
|
_static_mutex[i].mutex.hold = 0;
|
|
|
|
if (err != RT_EOK)
|
|
{
|
|
return SQLITE_ERROR;
|
|
}
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static sqlite3_mutex * _rtthread_mtx_alloc(int id)
|
|
{
|
|
sqlite3_mutex *p = NULL;
|
|
|
|
switch (id)
|
|
{
|
|
case SQLITE_MUTEX_FAST:
|
|
case SQLITE_MUTEX_RECURSIVE:
|
|
p = sqlite3Malloc(sizeof(sqlite3_mutex));
|
|
|
|
if (p != NULL)
|
|
{
|
|
rt_mutex_init(&p->mutex, "sqlmtx", RT_IPC_FLAG_PRIO);
|
|
p->id = id;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(id - 2 >= 0);
|
|
assert(id - 2 < ArraySize(_static_mutex) );
|
|
p = &_static_mutex[id - 2];
|
|
p->id = id;
|
|
break;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
static void _rtthread_mtx_free(sqlite3_mutex * p)
|
|
{
|
|
assert(p != 0);
|
|
|
|
rt_mutex_detach(&p->mutex);
|
|
|
|
switch (p->id)
|
|
{
|
|
case SQLITE_MUTEX_FAST:
|
|
case SQLITE_MUTEX_RECURSIVE:
|
|
sqlite3_free(p);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void _rtthread_mtx_enter(sqlite3_mutex *p)
|
|
{
|
|
assert(p != 0);
|
|
|
|
rt_mutex_take(&p->mutex, RT_WAITING_FOREVER);
|
|
}
|
|
|
|
static int _rtthread_mtx_try(sqlite3_mutex *p)
|
|
{
|
|
assert(p != 0);
|
|
|
|
if (rt_mutex_take(&p->mutex, RT_WAITING_NO) != RT_EOK)
|
|
{
|
|
return SQLITE_BUSY;
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static void _rtthread_mtx_leave(sqlite3_mutex *p)
|
|
{
|
|
assert(p != 0);
|
|
|
|
rt_mutex_release(&p->mutex);
|
|
}
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
|
|
/*
|
|
If the argument to sqlite3_mutex_held() is a NULL pointer then the routine
|
|
should return 1. This seems counter-intuitive since clearly the mutex cannot
|
|
be held if it does not exist. But the reason the mutex does not exist is
|
|
because the build is not using mutexes. And we do not want the assert()
|
|
containing the call to sqlite3_mutex_held() to fail, so a non-zero return
|
|
is the appropriate thing to do. The sqlite3_mutex_notheld() interface should
|
|
also return 1 when given a NULL pointer.
|
|
*/
|
|
static int _rtthread_mtx_held(sqlite3_mutex *p)
|
|
{
|
|
if (p != 0)
|
|
{
|
|
if ((rt_thread_self() == p->mutex.owner) && (p->mutex.hold > 0))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int _rtthread_mtx_noheld(sqlite3_mutex *p)
|
|
{
|
|
if (_rtthread_mtx_held(p))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void)
|
|
{
|
|
static const sqlite3_mutex_methods sMutex = {
|
|
_rtthread_mtx_init,
|
|
_rtthread_mtx_end,
|
|
_rtthread_mtx_alloc,
|
|
_rtthread_mtx_free,
|
|
_rtthread_mtx_enter,
|
|
_rtthread_mtx_try,
|
|
_rtthread_mtx_leave,
|
|
#ifdef SQLITE_DEBUG
|
|
_rtthread_mtx_held,
|
|
_rtthread_mtx_noheld
|
|
#else
|
|
0,
|
|
0
|
|
#endif
|
|
};
|
|
|
|
return &sMutex;
|
|
}
|
|
|
|
#endif /* SQLITE_MUTEX_RTTHREAD */
|
|
|