📄 ptsynch.c
字号:
/* tuck these away 'till later */ saved_entries = mon->entryCount; mon->entryCount = 0; _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner); _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); rv = PR_WaitCondVar(mon->cvar, timeout); /* reinstate the intresting information */ mon->entryCount = saved_entries; _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner); return rv;} /* PR_Wait */PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon){ PR_ASSERT(NULL != mon); /* we'd better be locked */ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex)); /* and the entries better be positive */ PR_ASSERT(mon->entryCount > 0); /* and it better be by us */ PR_ASSERT(pthread_equal(mon->owner, pthread_self())); pt_PostNotifyToCvar(mon->cvar, PR_FALSE); return PR_SUCCESS;} /* PR_Notify */PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon){ PR_ASSERT(mon != NULL); /* we'd better be locked */ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex)); /* and the entries better be positive */ PR_ASSERT(mon->entryCount > 0); /* and it better be by us */ PR_ASSERT(pthread_equal(mon->owner, pthread_self())); pt_PostNotifyToCvar(mon->cvar, PR_TRUE); return PR_SUCCESS;} /* PR_NotifyAll *//**************************************************************//**************************************************************//**************************SEMAPHORES**************************//**************************************************************//**************************************************************/PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore){ static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_PostSem", "locks & condition variables"); PR_Lock(semaphore->cvar->lock); PR_NotifyCondVar(semaphore->cvar); semaphore->count += 1; PR_Unlock(semaphore->cvar->lock);} /* PR_PostSem */PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *semaphore){ PRStatus status = PR_SUCCESS; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_WaitSem", "locks & condition variables"); PR_Lock(semaphore->cvar->lock); while ((semaphore->count == 0) && (PR_SUCCESS == status)) status = PR_WaitCondVar(semaphore->cvar, PR_INTERVAL_NO_TIMEOUT); if (PR_SUCCESS == status) semaphore->count -= 1; PR_Unlock(semaphore->cvar->lock); return status;} /* PR_WaitSem */PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *semaphore){ static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_DestroySem", "locks & condition variables"); PR_DestroyLock(semaphore->cvar->lock); PR_DestroyCondVar(semaphore->cvar); PR_DELETE(semaphore);} /* PR_DestroySem */PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value){ PRSemaphore *semaphore; static PRBool unwarned = PR_TRUE; if (!_pr_initialized) _PR_ImplicitInitialization(); if (unwarned) unwarned = _PR_Obsolete( "PR_NewSem", "locks & condition variables"); semaphore = PR_NEWZAP(PRSemaphore); if (NULL != semaphore) { PRLock *lock = PR_NewLock(); if (NULL != lock) { semaphore->cvar = PR_NewCondVar(lock); if (NULL != semaphore->cvar) { semaphore->count = value; return semaphore; } PR_DestroyLock(lock); } PR_DELETE(semaphore); } return NULL;}/* * Define the interprocess named semaphore functions. * There are three implementations: * 1. POSIX semaphore based; * 2. System V semaphore based; * 3. unsupported (fails with PR_NOT_IMPLEMENTED_ERROR). */#ifdef _PR_HAVE_POSIX_SEMAPHORES#include <fcntl.h>PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value){ PRSem *sem; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return NULL; } sem = PR_NEW(PRSem); if (NULL == sem) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } if (flags & PR_SEM_CREATE) { int oflag = O_CREAT; if (flags & PR_SEM_EXCL) oflag |= O_EXCL; sem->sem = sem_open(osname, oflag, mode, value); } else { sem->sem = sem_open(osname, 0); } if ((sem_t *) -1 == sem->sem) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_DELETE(sem); return NULL; } return sem;}PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem){ int rv; rv = sem_wait(sem->sem); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS;}PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem){ int rv; rv = sem_post(sem->sem); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS;}PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem){ int rv; rv = sem_close(sem->sem); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } PR_DELETE(sem); return PR_SUCCESS;}PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name){ int rv; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return PR_FAILURE; } rv = sem_unlink(osname); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS;} #elif defined(_PR_HAVE_SYSV_SEMAPHORES)#include <fcntl.h>#include <sys/sem.h>/* * From the semctl(2) man page in glibc 2.0 */#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \ || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI)/* union semun is defined by including <sys/sem.h> */#else/* according to X/OPEN we have to define it ourselves */union semun { int val; struct semid_ds *buf; unsigned short *array;};#endif/* * 'a' (97) is the final closing price of NSCP stock. */#define NSPR_IPC_KEY_ID 'a' /* the id argument for ftok() */#define NSPR_SEM_MODE 0666PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value){ PRSem *sem; key_t key; union semun arg; struct sembuf sop; struct semid_ds seminfo;#define MAX_TRIES 60 PRIntn i; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return NULL; } /* Make sure the file exists before calling ftok. */ if (flags & PR_SEM_CREATE) { int osfd = open(osname, O_RDWR|O_CREAT, mode); if (-1 == osfd) { _PR_MD_MAP_OPEN_ERROR(errno); return NULL; } if (close(osfd) == -1) { _PR_MD_MAP_CLOSE_ERROR(errno); return NULL; } } key = ftok(osname, NSPR_IPC_KEY_ID); if ((key_t)-1 == key) { _PR_MD_MAP_DEFAULT_ERROR(errno); return NULL; } sem = PR_NEW(PRSem); if (NULL == sem) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } if (flags & PR_SEM_CREATE) { sem->semid = semget(key, 1, mode|IPC_CREAT|IPC_EXCL); if (sem->semid >= 0) { /* creator of a semaphore is responsible for initializing it */ arg.val = 0; if (semctl(sem->semid, 0, SETVAL, arg) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_DELETE(sem); return NULL; } /* call semop to set sem_otime to nonzero */ sop.sem_num = 0; sop.sem_op = value; sop.sem_flg = 0; if (semop(sem->semid, &sop, 1) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_DELETE(sem); return NULL; } return sem; } if (errno != EEXIST || flags & PR_SEM_EXCL) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_DELETE(sem); return NULL; } } sem->semid = semget(key, 1, NSPR_SEM_MODE); if (sem->semid == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_DELETE(sem); return NULL; } for (i = 0; i < MAX_TRIES; i++) { arg.buf = &seminfo; semctl(sem->semid, 0, IPC_STAT, arg); if (seminfo.sem_otime != 0) break; sleep(1); } if (i == MAX_TRIES) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); PR_DELETE(sem); return NULL; } return sem;}PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem){ struct sembuf sop; sop.sem_num = 0; sop.sem_op = -1; sop.sem_flg = 0; if (semop(sem->semid, &sop, 1) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS;}PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem){ struct sembuf sop; sop.sem_num = 0; sop.sem_op = 1; sop.sem_flg = 0; if (semop(sem->semid, &sop, 1) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS;}PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem){ PR_DELETE(sem); return PR_SUCCESS;}PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name){ key_t key; int semid; /* On some systems (e.g., glibc 2.0) semctl requires a fourth argument */ union semun unused; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return PR_FAILURE; } key = ftok(osname, NSPR_IPC_KEY_ID); if ((key_t) -1 == key) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } if (unlink(osname) == -1) { _PR_MD_MAP_UNLINK_ERROR(errno); return PR_FAILURE; } semid = semget(key, 1, NSPR_SEM_MODE); if (-1 == semid) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } unused.val = 0; if (semctl(semid, 0, IPC_RMID, unused) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS;}#else /* neither POSIX nor System V semaphores are available */PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value){ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL;}PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem){ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem){ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem){ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name){ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}#endif /* end of interprocess named semaphore functions *//**************************************************************//**************************************************************//******************ROUTINES FOR DCE EMULATION******************//**************************************************************//**************************************************************/#include "prpdce.h"PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock){ PRIntn rv = pthread_mutex_trylock(&lock->mutex); if (rv == PT_TRYLOCK_SUCCESS) { PR_ASSERT(PR_FALSE == lock->locked); lock->locked = PR_TRUE; lock->owner = pthread_self(); } /* XXX set error code? */ return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;} /* PRP_TryLock */PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void){ PRCondVar *cv; if (!_pr_initialized) _PR_ImplicitInitialization(); cv = PR_NEW(PRCondVar); if (cv != NULL) { int rv; rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); PR_ASSERT(0 == rv); cv->lock = _PR_NAKED_CV_LOCK; } return cv;} /* PRP_NewNakedCondVar */PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar){ int rv; rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);#if defined(DEBUG) memset(cvar, 0xaf, sizeof(PRCondVar));#endif PR_DELETE(cvar);} /* PRP_DestroyNakedCondVar */PR_IMPLEMENT(PRStatus) PRP_NakedWait( PRCondVar *cvar, PRLock *ml, PRIntervalTime timeout){ PRIntn rv; PR_ASSERT(cvar != NULL); /* XXX do we really want to assert this in a naked wait? */ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(ml->mutex)); if (timeout == PR_INTERVAL_NO_TIMEOUT) rv = pthread_cond_wait(&cvar->cv, &ml->mutex); else rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout); if (rv != 0) { _PR_MD_MAP_DEFAULT_ERROR(rv); return PR_FAILURE; } return PR_SUCCESS;} /* PRP_NakedWait */PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar){ int rv; PR_ASSERT(cvar != NULL); rv = pthread_cond_signal(&cvar->cv); PR_ASSERT(0 == rv); return PR_SUCCESS;} /* PRP_NakedNotify */PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar){ int rv; PR_ASSERT(cvar != NULL); rv = pthread_cond_broadcast(&cvar->cv); PR_ASSERT(0 == rv); return PR_SUCCESS;} /* PRP_NakedBroadcast */#endif /* defined(_PR_PTHREADS) *//* ptsynch.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -