|
|
| version 1.7, 2004/07/15 06:38:10 | version 1.24, 2024/11/04 17:36:49 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: commonly functions. | Parser: commonly functions. |
| Copyright(c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru> |
| */ | */ |
| static const char * const IDENT_COMMON_C="$Date$"; | |
| #include "pa_config_includes.h" | #include "pa_config_includes.h" |
| #include "pa_os.h" | #include "pa_os.h" |
| # if defined(WIN32) | volatile const char * IDENT_PA_OS_C="$Id$" IDENT_PA_OS_H; |
| # include <windows.h> | |
| # endif | |
| #ifdef HAVE_FLOCK | unsigned int pa_lock_attempts=PA_LOCK_ATTEMPTS; |
| #ifdef _MSC_VER | |
| #include <windows.h> | |
| int pa_lock_shared_blocking(int fd) { return flock(fd, LOCK_SH); } | #define PA_SH_LOCK 2 |
| int pa_lock_exclusive_blocking(int fd) { return flock(fd, LOCK_EX); } | #define PA_EX_LOCK 1 |
| int pa_lock_exclusive_nonblocking(int fd) { return flock(fd, LOCK_EX || LOCK_NB); } | #define PA_ULOCK 0 |
| int pa_unlock(int fd) { return flock(fd, LOCK_UN); } | #define FLOCK(operation) int status=pa_flock(fd, operation); |
| #define ERRNO pa_errno() | |
| int pa_flock(int fd, int operation) { | |
| HANDLE hFile = (HANDLE)_get_osfhandle(fd); | |
| if (hFile == INVALID_HANDLE_VALUE) { | |
| return -1; | |
| } | |
| OVERLAPPED overlapped = {0}; | |
| if (operation == PA_ULOCK) { | |
| return UnlockFileEx(hFile, 0, MAXDWORD, MAXDWORD, &overlapped) ? 0 : -1; | |
| } else { | |
| DWORD flags = LOCKFILE_FAIL_IMMEDIATELY; | |
| if (operation == PA_EX_LOCK) { | |
| flags |= LOCKFILE_EXCLUSIVE_LOCK; | |
| } | |
| return LockFileEx(hFile, flags, 0, MAXDWORD, MAXDWORD, &overlapped) ? 0 : -1; | |
| } | |
| } | |
| int pa_errno() { | |
| switch(GetLastError()) { | |
| case ERROR_LOCK_VIOLATION: | |
| case ERROR_SHARING_VIOLATION: | |
| return EBUSY; | |
| case ERROR_IO_PENDING: | |
| return EAGAIN; | |
| case ERROR_INVALID_HANDLE: | |
| return EBADF; | |
| case ERROR_NOT_LOCKED: | |
| return ENOLCK; | |
| } | |
| return EACCES; | |
| } | |
| #else | #else |
| #ifdef HAVE__LOCKING | |
| #define FLOCK(operation) lseek(fd, 0, SEEK_SET); return _locking(fd, operation, 1) | #define ERRNO errno |
| int pa_lock_shared_blocking(int fd) { FLOCK(_LK_LOCK); } | |
| int pa_lock_exclusive_blocking(int fd) { FLOCK(_LK_LOCK); } | #ifdef HAVE_FLOCK |
| int pa_lock_exclusive_nonblocking(int fd) { FLOCK(_LK_NBLCK); } | |
| int pa_unlock(int fd) { FLOCK(_LK_UNLCK); } | #define PA_SH_LOCK LOCK_SH|LOCK_NB |
| #define PA_EX_LOCK LOCK_EX|LOCK_NB | |
| #define PA_ULOCK LOCK_UN | |
| #define FLOCK(operation) int status=flock(fd, operation); | |
| #else | #else |
| #ifdef HAVE_FCNTL | #ifdef HAVE_FCNTL |
| #define FLOCK(cmd, arg) struct flock ls={arg, SEEK_SET}; return fcntl(fd, cmd, &ls) | #define PA_SH_LOCK F_RDLCK |
| int pa_lock_shared_blocking(int fd) { FLOCK(F_SETLKW, F_RDLCK); } | #define PA_EX_LOCK F_WRLCK |
| int pa_lock_exclusive_blocking(int fd) { FLOCK(F_SETLKW, F_WRLCK); } | #define PA_ULOCK F_UNLCK |
| int pa_lock_exclusive_nonblocking(int fd) { FLOCK(F_SETLK, F_RDLCK); } | #define FLOCK(operation) struct flock ls={operation, SEEK_SET}; int status=fcntl(fd, F_SETLK, &ls); |
| int pa_unlock(int fd) { FLOCK(F_SETLK, F_UNLCK); } | |
| #else | #else |
| #ifdef HAVE_LOCKF | #ifdef HAVE_LOCKF |
| #define FLOCK(fd, operation) lseek(fd, 0, SEEK_SET); return lockf(fd, operation, 1) | #define PA_SH_LOCK F_TLOCK |
| int pa_lock_shared_blocking(int fd) { FLOCK(F_LOCK); } // on intel solaris man doesn't have doc on shared blocking | #define PA_EX_LOCK F_TLOCK |
| int pa_lock_exclusive_blocking(int fd) { FLOCK(F_LOCK); } | #define PA_ULOCK F_ULOCK |
| int pa_lock_exclusive_nonblocking(int fd) { FLOCK(F_TLOCK); } | #define FLOCK(operation) lseek(fd, 0, SEEK_SET); int status=lockf(fd, operation, 1); |
| int pa_unlock(int fd) { FLOCK(F_TLOCK); } | |
| #else | #else |
| Line 55 int pa_unlock(int fd) { FLOCK(F_TLOCK); | Line 89 int pa_unlock(int fd) { FLOCK(F_TLOCK); |
| #endif | #endif |
| #endif | #endif |
| #endif | #endif |
| #endif | #endif |
| int pa_lock(int fd, int attempts, int operation){ | |
| while(true){ | |
| FLOCK(operation); | |
| if(status==0) | |
| return 0; | |
| if(--attempts<=0) | |
| return ERRNO; | |
| pa_sleep(PA_LOCK_WAIT_TIMEOUT_SECS, PA_LOCK_WAIT_TIMEOUT_USECS); | |
| } | |
| }; | |
| int pa_lock_shared_blocking(int fd) { | |
| return pa_lock(fd, pa_lock_attempts, PA_SH_LOCK); | |
| } | |
| int pa_lock_exclusive_blocking(int fd) { | |
| return pa_lock(fd, pa_lock_attempts, PA_EX_LOCK); | |
| } | |
| int pa_lock_exclusive_nonblocking(int fd) { | |
| return pa_lock(fd, 1, PA_EX_LOCK); | |
| } | |
| int pa_unlock(int fd) { | |
| return pa_lock(fd, 1, PA_ULOCK); | |
| } | |
| int pa_sleep(unsigned long secs, unsigned long usecs) { | int pa_sleep(unsigned long secs, unsigned long usecs) { |
| for (; usecs >= 1000000; ++secs, usecs -= 1000000); | if(usecs >= 1000000){ |
| secs += usecs/1000000; | |
| usecs = usecs%1000000; | |
| } | |
| #ifdef WIN32 | #ifdef _MSC_VER |
| Sleep(secs * 1000 + usecs / 1000); | Sleep(secs * 1000 + usecs / 1000); |
| return 0; | return 0; |
| #else | #else |