📄 stafeventsem.cpp
字号:
/*****************************************************************************//* Software Testing Automation Framework (STAF) *//* (C) Copyright IBM Corp. 2001 *//* *//* This software is licensed under the Common Public License (CPL) V1.0. *//*****************************************************************************/#include <unistd.h>#include <pthread.h>#include <fcntl.h>#include <sys/msg.h>#include <sys/time.h>#include <sys/stat.h>#include <errno.h>#include "STAFOSTypes.h"#include "STAFEventSem.h"static int getNumMsgs(int msgqid);struct STAFEventSemPrivateData{ enum State { kPosted = 0, kReset = 1 }; pthread_mutex_t fMutex; pthread_cond_t fCond; State fState;};struct STAFEventSemSharedData{ int fMsgQID;};struct STAFMsgPost{ long val; unsigned int data;};struct STAFEventSemImplementation{ enum Type { kPrivate = 0, kShared = 1 }; Type fType; union { STAFEventSemPrivateData fPrivate; STAFEventSemSharedData fShared; };};STAFRC_t STAFEventSemConstruct(STAFEventSem_t *pEvent, const char *name, unsigned int *osRC){ STAFRC_t rc = kSTAFOk; if (pEvent == 0) return kSTAFInvalidObject; try { *pEvent = new STAFEventSemImplementation; STAFEventSemImplementation &eventSem = **pEvent; if (name == 0) { eventSem.fType = STAFEventSemImplementation::kPrivate; eventSem.fPrivate.fState = STAFEventSemPrivateData::kReset; int rc2 = pthread_mutex_init(&eventSem.fPrivate.fMutex, 0); if (rc2 != 0) { if (osRC) *osRC = rc2; delete *pEvent; return kSTAFBaseOSError; } rc2 = pthread_cond_init(&eventSem.fPrivate.fCond, 0); if (rc2 != 0) { if (osRC) *osRC = rc2; pthread_mutex_destroy(&eventSem.fPrivate.fMutex); delete *pEvent; return kSTAFBaseOSError; } } else { // Shared event semaphore return kSTAFInvalidParm; // XXX: Shared event semaphores don't currently work and are not // being used. So, commented out this code because was getting // the following error compiling on Solaris after adding // -D_FILE_OFFFSET_BITS=64 to makefile.solaris for large file // support: // *** Compiling STAFEventSem.o *** // In function `STAFRC_t STAFEventSemConstruct(...)' // implicit declaration of function `int open(...)' // make: *** [.../stafif/STAFEventSem.o] Error 1 /* eventSem.fType = STAFEventSemImplementation::kShared; STAFString theName("/tmp/STAFEventSem_"); theName += name; const char *theNameInCurrentCodePage = theName.toCurrentCodePage()->buffer(); int initEvent = 1; int fileID = open(theNameInCurrentCodePage, O_CREAT | O_EXCL | O_RDONLY); if ((fileID == -1) && (errno == EEXIST)) { initEvent = 0; fileID = open(theNameInCurrentCodePage, O_CREAT | O_RDONLY); } if (fileID == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } int closeRC = close(fileID); if (closeRC == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } int chmodRC = chmod(theNameInCurrentCodePage, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (chmodRC == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } key_t key = ftok(theNameInCurrentCodePage, 1); if (key == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } eventSem.fShared.fMsgQID = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (eventSem.fShared.fMsgQID == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } */ } } catch (...) { rc = kSTAFUnknownError; if (osRC) *osRC = 0xFFFFFFFF; } return rc;}STAFRC_t STAFEventSemPost(STAFEventSem_t pEvent, unsigned int *osRC){ STAFEventSemImplementation &eventSem = *pEvent; if (eventSem.fType == STAFEventSemImplementation::kPrivate) { unsigned int rc2 = 0; if ((rc2 = pthread_mutex_lock(&eventSem.fPrivate.fMutex)) != 0) { if (osRC) *osRC = rc2; return kSTAFBaseOSError; } // If the state is reset then broadcast all threads // waiting for the condition variable if (eventSem.fPrivate.fState == STAFEventSemPrivateData::kReset) { if ((rc2 = pthread_cond_broadcast(&eventSem.fPrivate.fCond)) != 0) { if (osRC) *osRC = rc2; pthread_mutex_unlock(&eventSem.fPrivate.fMutex); return kSTAFBaseOSError; } eventSem.fPrivate.fState = STAFEventSemPrivateData::kPosted; // XXX: Should I check the return code here and report back to the // caller? Same thing in several places below. } pthread_mutex_unlock(&eventSem.fPrivate.fMutex); } else { STAFMsgPost postcmd = { 1, 1 }; int postrc = msgsnd(eventSem.fShared.fMsgQID, &postcmd, sizeof(unsigned int), IPC_NOWAIT); if (postrc == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } } return kSTAFOk;}STAFRC_t STAFEventSemReset(STAFEventSem_t pEvent, unsigned int *osRC){ STAFEventSemImplementation &eventSem = *pEvent; if (eventSem.fType == STAFEventSemImplementation::kPrivate) { unsigned int rc2 = 0; if ((rc2 = pthread_mutex_lock(&eventSem.fPrivate.fMutex)) != 0) { if (osRC) *osRC = rc2; return kSTAFBaseOSError; } eventSem.fPrivate.fState = STAFEventSemPrivateData::kReset; pthread_mutex_unlock(&eventSem.fPrivate.fMutex); } else { int numMsgs = getNumMsgs(eventSem.fShared.fMsgQID); if (numMsgs == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } STAFMsgPost data = { 0 }; for (int i = 0; i < numMsgs; ++i) { // XXX: We simply ignore errors while emptying the queue. // We might want to be smarter here. int rc = msgrcv(eventSem.fShared.fMsgQID, &data, sizeof(unsigned int), 0, MSG_NOERROR | IPC_NOWAIT); } } return kSTAFOk;}STAFRC_t STAFEventSemWait(STAFEventSem_t pEvent, unsigned int timeout, unsigned int *osRC){ STAFRC_t rc = kSTAFOk; if (pEvent == 0) return kSTAFInvalidObject; STAFEventSemImplementation &eventSem = *pEvent; if (eventSem.fType == STAFEventSemImplementation::kPrivate) { unsigned int timeNow = (unsigned int)time(0); unsigned int rc2 = 0; if ((rc2 = pthread_mutex_lock(&eventSem.fPrivate.fMutex)) != 0) { if (osRC) *osRC = rc2; return kSTAFBaseOSError; } if (eventSem.fPrivate.fState == STAFEventSemPrivateData::kPosted) { rc = kSTAFOk; } else { const struct timespec theTimeout = { timeNow + (timeout / 1000), (timeout % 1000) * 1000 }; int rc2 = EINTR; while ((rc2 == EINTR) || ((timeout == STAF_EVENT_SEM_INDEFINITE_WAIT) && (eventSem.fPrivate.fState == STAFEventSemPrivateData::kReset))) { if (timeout == STAF_EVENT_SEM_INDEFINITE_WAIT) { rc2 = pthread_cond_wait(&eventSem.fPrivate.fCond, &eventSem.fPrivate.fMutex); } else { rc2 = pthread_cond_timedwait(&eventSem.fPrivate.fCond, &eventSem.fPrivate.fMutex, &theTimeout); } } // XXX: Hack Hack! z/OS returns EAGAIN instead of ETIMEDOUT // This is not how this will ultimately be coded. This will // probably require the same fix as for the Solaris 9 bug if ((rc2 == ETIMEDOUT) || (rc2 == EAGAIN)) { rc = kSTAFTimeout; } else if (rc2 != 0) { rc = kSTAFBaseOSError; if (osRC) *osRC = rc2; } } pthread_mutex_unlock(&eventSem.fPrivate.fMutex); } else { // XXX: We will need to do something different for shared Event sems // It appears that only AIX allows this enhanced use of select() // for message queues. int readmsg = eventSem.fShared.fMsgQID; timeval timeOut = { (timeout / 1000), (timeout % 1000) }; int selRC = select((1 << 16), (fd_set *)&readmsg, 0 , 0, timeout ? &timeOut : 0); if (selRC == -1) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } rc = selRC ? kSTAFOk : kSTAFBaseOSError; } return rc;}STAFRC_t STAFEventSemQuery(STAFEventSem_t pEvent, STAFEventSemState_t *pState, unsigned int *osRC){ STAFRC_t rc = kSTAFOk; if (pEvent == 0) return kSTAFInvalidObject; if (pState == 0) return kSTAFInvalidParm; STAFEventSemImplementation &eventSem = *pEvent; if (eventSem.fType == STAFEventSemImplementation::kPrivate) { unsigned int rc2 = 0; if ((rc2 = pthread_mutex_lock(&eventSem.fPrivate.fMutex)) != 0) { if (osRC) *osRC = rc2; return kSTAFBaseOSError; } *pState = (eventSem.fPrivate.fState == STAFEventSemPrivateData::kReset) ? kSTAFEventSemReset : kSTAFEventSemPosted; pthread_mutex_unlock(&eventSem.fPrivate.fMutex); } else { int numMsgs = getNumMsgs(eventSem.fShared.fMsgQID); if (numMsgs == -1) { if (osRC) *osRC = 1; return kSTAFBaseOSError; } *pState = numMsgs ? kSTAFEventSemPosted : kSTAFEventSemReset; } return rc;}STAFRC_t STAFEventSemDestruct(STAFEventSem_t *pEvent, unsigned int *osRC){ STAFRC_t rc = kSTAFOk; if (pEvent == 0) return kSTAFInvalidObject; STAFEventSemImplementation &eventSem = **pEvent; if (eventSem.fType == STAFEventSemImplementation::kPrivate) { unsigned int rc2 = 0; if ((rc2 = pthread_cond_destroy(&eventSem.fPrivate.fCond)) != 0) { rc = kSTAFBaseOSError; if (osRC) *osRC = rc2; } if ((rc2 = pthread_mutex_destroy(&eventSem.fPrivate.fMutex)) != 0) { rc = kSTAFBaseOSError; if (osRC) *osRC = rc2; } } else { // Note: We do not remove the message queue here, as other processes // may be using it, and it is a shared resource } delete *pEvent; *pEvent = 0; return rc;}int getNumMsgs(int msgqid){ msqid_ds msgData = { 0 }; int rc = msgctl(msgqid, IPC_STAT, &msgData); return (rc == -1) ? rc : msgData.msg_qnum;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -