Fix VxWorks epicsThreadMustJoin() problems

taskWait() actually returns OK on timeout, so drop the timeout warning
(the other implementations don't have one).
The taskWait() may return ERROR with S_objLib_OBJ_ID_ERROR if the target
thread has higher priority; this indicates a successful join, because
we already did a rendezvous using joinSem.
Delete joinSem *after* calling taskSpareFieldSet(), in case it matters.
This commit is contained in:
Andrew Johnson
2020-01-02 16:39:10 -06:00
parent 06728e0e0b
commit 05e0381b19
+16 -26
View File
@@ -211,16 +211,20 @@ void epicsThreadAwaitingJoin(int tid)
if (status)
perror("epicsThreadAwaitingJoin");
semDelete(joinSem);
taskSpareFieldSet(tid, joinField, 0);
semDelete(joinSem);
}
#define PREPARE_JOIN(tid, joinable) \
taskSpareFieldSet(tid, joinField, \
joinable ? (int) semBCreate(SEM_Q_FIFO, SEM_EMPTY) : 0)
#define AWAIT_JOIN(tid) epicsThreadAwaitingJoin(tid)
#define AWAIT_JOIN(tid) \
epicsThreadAwaitingJoin(tid)
#else
#define PREPARE_JOIN(tid, joinable)
#define AWAIT_JOIN(tid)
#endif
static void createFunction(EPICSTHREADFUNC func, void *parm)
@@ -297,48 +301,34 @@ void epicsThreadMustJoin(epicsThreadId id)
joinSem = (SEM_ID) taskSpareFieldGet(tid, joinField);
if ((int) joinSem == ERROR) {
errlogPrintf("%s: Thread '%s' no longer exists.\n",
fn, taskName(tid));
errlogPrintf("%s: Thread %#x no longer exists.\n", fn, tid);
return;
}
if (tid == taskIdSelf()) {
if (joinSem) {
semDelete(joinSem);
taskSpareFieldSet(tid, joinField, 0);
semDelete(joinSem);
}
else {
errlogPrintf("%s: Self-join of unjoinable thread '%s'\n",
fn, taskName(tid));
errlogPrintf("%s: Thread '%s' (%#x) can't self-join.\n",
fn, epicsThreadGetNameSelf(), tid);
}
return;
}
if (!joinSem) {
cantProceed("%s: Thread '%s' is not joinable.\n",
fn, taskName(tid));
cantProceed("%s: Thread '%s' (%#x) is not joinable.\n",
fn, taskName(tid), tid);
return;
}
semGive(joinSem); /* Rendezvous with thread */
status = taskWait(tid, JOIN_WARNING_TIMEOUT);
if (status && errno == S_objLib_OBJ_TIMEOUT) {
errlogPrintf("Warning: %s still waiting for thread '%s'\n",
fn, taskName(tid));
status = taskWait(tid, WAIT_FOREVER);
}
if (status) {
if (errno == S_taskLib_ILLEGAL_OPERATION) {
errlogPrintf("%s: This shouldn't happen!\n", fn);
}
else if (errno == S_objLib_OBJ_ID_ERROR) {
errlogPrintf("%s: %x is not a known thread\n", fn, tid);
}
else {
perror(fn);
}
cantProceed(fn);
status = taskWait(tid, WAIT_FOREVER);
if (status && errno != S_objLib_OBJ_ID_ERROR) {
perror(fn);
cantProceed("%s: ", fn);
}
#endif
}