Files
QNX/lib/c/stdio/xsyslock.c
2025-08-20 19:02:58 +08:00

309 lines
5.5 KiB
C

/* xsyslock.c -- thread locking and unlocking functions */
#include <stdio.h>
#include "xmtx.h"
#ifdef __QNX__
#include <errno.h>
#endif
#if defined(__BORLANDC__)
#pragma warn -par
#endif /* defined(__BORLANDC__) */
_STD_BEGIN
#if !_MULTI_THREAD
void (_Locksyslock)(int lockno)
{ /* set a system lock */
}
void (_Unlocksyslock)(int lockno)
{ /* clear a system lock */
}
#else /* _MULTI_THREAD */
#define INIT _Once(&syslock_o, _Initlocks)
#define TIDY _CSTD _Atexit(&_Clearlocks)
static _Once_t syslock_o = _ONCE_T_INIT;
#if _HAS_DINKUM_CLIB
#define _MAX_FLOCK FOPEN_MAX
#ifdef __QNX__
typedef struct _file_list {
_Rmtx *_Flock;
struct _file_list *_Fnext;
} _file_list;
static int _file_list_count;
static _Rmtx _Flist_mtx;
struct _file_list *_Flist_head = NULL;
#else /* __QNX__ */
static _Rmtx file_mtx[_MAX_FLOCK];
static int max_flock = 0;
#endif /* __QNX__ */
#endif /* _HAS_DINKUM_CLIB */
static int max_lock = 0;
static _Rmtx mtx[_MAX_LOCK];
#ifdef __QNX__
/* We don't need the atexit handlers */
#undef TIDY
#define TIDY
#define UNLOCK_MTX(_Mtx, thr) \
if(MTXP(_Mtx) && pthread_equal(MTX_OWNER(_Mtx), thr)) { \
if (MTXP(_Mtx)->cnt) { \
pthread_mutex_unlock(&MTXP(_Mtx)->mtx); \
MTXP(_Mtx)->cnt = 0; \
} \
}
void _Unlockfilemtx() {
FILE *fp;
pthread_t thr = pthread_self();
_Locksyslock(_LOCK_STREAM);
for (fp = _Files[0]; fp; fp = fp->_NextFile) {
UNLOCK_MTX(&fp->_Flock, thr);
}
_Unlocksyslock(_LOCK_STREAM);
}
void _Unlocksysmtx() {
int loop;
_Rmtx *_Mtx;
pthread_t thr = pthread_self();
for (loop = 0; loop < _MAX_LOCK; ++loop) {
_Mtx = &mtx[loop];
UNLOCK_MTX(_Mtx, thr);
}
}
static void _Lockfilealloc(FILE *str) {
struct _file_list *fptr;
if (_Flist_head->_Fnext == NULL) // make lock
{
_Mtxinit(&str->_Flock);
}
else // just take one
{
_Mtxlock(&_Flist_mtx);
fptr = _Flist_head->_Fnext;
_Flist_head->_Fnext = fptr->_Fnext;
fptr->_Fnext = NULL;
_Mtxunlock(&_Flist_mtx);
str->_Flock = fptr->_Flock;
free(fptr);
_file_list_count--;
}
}
int _Ftrylockfile(FILE *fp) {
int ret = EOK;
pthread_t tid = pthread_self();
_Rmtx **_Mtx;
if (fp != 0)
{
if (fp->_Flock == NULL) // need to acquire lock
{
_Lockfilealloc(fp);
}
_Mtx = (_Rmtx **)&fp->_Flock;
if (MTXP(_Mtx)->cnt && pthread_equal(MTX_OWNER(_Mtx), tid)) {
++MTXP(_Mtx)->cnt;
} else if ((ret = pthread_mutex_trylock(&MTXP(_Mtx)->mtx)) == EOK) {
++MTXP(_Mtx)->cnt;
}
}
return (ret);
}
#endif
void _Clearlocks(void)
{ /* clear all locks at program termination */
#ifdef __QNX__
/* note that this will only clear locks left in lock queue */
struct _file_list *fptr, *nextptr;
fptr = _Flist_head;
while (fptr)
{
nextptr = fptr->_Fnext;
if (fptr->_Flock)
_Mtxdst(fptr->_Flock);
free(fptr);
fptr = nextptr;
}
_file_list_count = 0;
#else /* __QNX__ */
int count;
#if _HAS_DINKUM_CLIB
max_flock = 0;
for (count = 0; count < _MAX_FLOCK; ++count)
_Mtxdst(&file_mtx[count]);
#endif /* _HAS_DINKUM_CLIB */
max_lock = 0;
for (count = 0; count < _MAX_LOCK; ++count)
_Mtxdst(&mtx[count]);
#endif /* __QNX__ */
}
void _Initlocks(void)
{ /* initialize all locks on first call to _Locksyslock */
#ifdef __QNX__
struct _file_list *fptr, *tmpptr;
fptr = _Flist_head;
while (fptr != NULL)
{
tmpptr = fptr->_Fnext;
if (fptr->_Flock != NULL)
{
_Mtxdst(fptr->_Flock);
}
free(fptr);
fptr = tmpptr;
}
_Flist_head = malloc(sizeof(struct _file_list));
_Flist_head->_Fnext = NULL;
_Mtxinit(&_Flist_mtx);
#else /* __QNX__ */
int count;
#if _WIN32_C_LIB
count = 0;
if (count != 0)
{ /* drag in our tolower, but don't force TLS setup */
int (tolower)(int);
(tolower)('A'); /* block linking of conflicting code */
}
#endif /* _WIN32_C_LIB */
#if _HAS_DINKUM_CLIB
for (count = 0; count < _MAX_FLOCK; ++count)
_Mtxinit(&file_mtx[count]);
max_flock = _MAX_FLOCK;
#endif /* _HAS_DINKUM_CLIB */
for (count = 0; count < _MAX_LOCK; ++count)
_Mtxinit(&mtx[count]);
max_lock = _MAX_LOCK;
TIDY;
#endif /* __QNX__ */
}
#if _HAS_DINKUM_CLIB
#ifdef __QNX__
void (_Releasefilelock)(FILE *str)
{
struct _file_list *fptr, *tmpptr;
if (str != 0)
{
if (_file_list_count < _MAX_FLOCK)
{
_Mtxlock(&_Flist_mtx);
fptr = _Flist_head;
tmpptr = fptr->_Fnext;
fptr->_Fnext = malloc(sizeof(struct _file_list));
fptr = fptr->_Fnext;
fptr->_Fnext = tmpptr;
fptr->_Flock = str->_Flock;
_file_list_count++;
_Mtxunlock(&_Flist_mtx);
}
else
{
_Mtxdst(str->_Flock);
}
}
}
#endif /* __QNX__ */
void (_Lockfilelock)(FILE *str)
{ /* set a file lock */
INIT;
#ifndef __QNX__
if (str != 0 && str->_Idx < max_flock)
_Mtxlock(&file_mtx[str->_Idx]);
#else /* !__QNX__ */
if (str != 0)
{
if (str->_Flock == NULL) // need to acquire lock
{
_Lockfilealloc(str);
}
_Mtxlock(&str->_Flock);
}
#endif /* !__QNX__ */
}
void (_Unlockfilelock)(FILE *str)
{ /* clear a system lock */
#ifndef __QNX__
if (str != 0 && str->_Idx < max_flock)
_Mtxunlock(&file_mtx[str->_Idx]);
#else /* !__QNX__ */
if (str != 0)
_Mtxunlock(&str->_Flock);
#endif /* !__QNX__ */
}
#endif /* _HAS_DINKUM_CLIB */
void (_Locksyslock)(int lockno)
{ /* set a system lock */
INIT;
if (lockno < max_lock)
_Mtxlock(&mtx[lockno]);
}
void (_Unlocksyslock)(int lockno)
{ /* clear a system lock */
if (lockno < max_lock)
_Mtxunlock(&mtx[lockno]);
}
#endif /* _MULTI_THREAD */
_STD_END
/*
* Copyright (c) 1992-2006 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
V5.00:1296 */
__SRCVERSION("xsyslock.c $Rev: 153052 $");