Merge branch 'PSI-3.14' of git.psi.ch:epics_base/base-3-14-12 into PSI-3.14

This commit is contained in:
2018-05-04 11:20:00 +02:00
7 changed files with 1117 additions and 44 deletions

View File

@@ -964,6 +964,7 @@ static void event_task (void *pParm)
} while( ! pendexit );
epicsMutexDestroy(evUser->firstque.writelock);
evUser->firstque.writelock = (epicsMutexId)0xdeadbeef;
{
struct event_que *nextque;
@@ -972,6 +973,7 @@ static void event_task (void *pParm)
while(ev_que){
nextque = ev_que->nextque;
epicsMutexDestroy(ev_que->writelock);
ev_que->writelock = (epicsMutexId)0xdeadbeef;
freeListFree(dbevEventQueueFreeList, ev_que);
ev_que = nextque;
}
@@ -980,6 +982,7 @@ static void event_task (void *pParm)
epicsEventDestroy(evUser->ppendsem);
epicsEventDestroy(evUser->pflush_sem);
epicsMutexDestroy(evUser->lock);
evUser->lock = (epicsMutexId)0xdeadbeef;
freeListFree(dbevEventUserFreeList, evUser);

View File

@@ -558,6 +558,186 @@ static MAC_ENTRY *create( MAC_HANDLE *handle, const char *name, int special )
return entry;
}
#define SUCCESS 0
#define NOVALUE 1
#define UNTERMINATED 2
#define DIVZERO 3
static int parseExpr( const char** pp, int* v, int level );
/* Value is a number or an expression in () */
static int parseValue( const char** pp, int* v )
{
int status;
int val;
const char *p = *pp;
int neg = 0;
while (isspace((unsigned char)*p)) p++;
if (*p == '+' || *p == '-') neg = *p++ == '-';
while (isspace((unsigned char)*p)) p++;
if (*p == '(')
{
p++;
if ((status = parseExpr(&p, &val, 0)) != SUCCESS) return status;
if (*p++ != ')')
{
printf("macLib: missing ) after '%s'\n", *pp);
return UNTERMINATED;
}
}
else
{
char* e;
val = strtol(p, &e, 0);
if (e == p) return NOVALUE;
p = e;
}
if (neg) val = -val;
*pp = p;
*v = val;
return SUCCESS;
}
/* Expr is a sum or product of Values or a conditional */
static int parseExpr( const char** pp, int* v, int level )
{
const char *p = *pp;
int o = 0;
int val0, val1, val2;
int status = SUCCESS;
int stat1, stat2;
val0 = 0;
/* handle sums and differences */
do {
if ((stat1 = parseValue(&p, &val1)) != SUCCESS)
{
if (o && stat1 == NOVALUE)
printf ("macLib: missing operand after '%c'\n", o);
return stat1;
}
while (isspace((unsigned char)*p)) p++;
o = *p;
/* handle products and quotients */
while (o == '*' || o == '/' || o == '%')
{
p++;
if ((stat2 = parseValue(&p, &val2)) != SUCCESS)
{
if (stat2 == NOVALUE)
printf ("macLib: missing operand after '%c'\n", o);
return stat2;
}
if (o == '*') val1 *= val2;
else if (val2 == 0)
{
status = DIVZERO;
val1 = 1;
}
else if (o == '/') val1 /= val2;
else val1 %= val2;
while (isspace((unsigned char)*p)) p++;
o = *p;
}
val0 += val1;
} while (o == '+' || o == '-');
/* handle comparisons */
o = *p;
if (o == '<' || o == '>')
{
p++;
if ((stat1 = parseExpr(&p, &val1, 1)) != SUCCESS)
{
if (stat1 == NOVALUE)
printf ("macLib: missing expression after '%c'\n", o);
return stat1;
}
if (o == '<')
val0 = (val0 < val1);
else
val0 = (val0 > val1);
}
/* handle conditionals */
if (*p == '?' && level == 0)
{
p++;
while (isspace((unsigned char)*p)) p++;
if (*p != ':')
{
stat1 = parseExpr(&p, &val1, 0);
}
else
{
val1 = val0;
stat1 = status;
}
if (*p != ':')
{
printf("macLib: missing : after '%s'\n", *pp);
return UNTERMINATED;
}
p++;
stat2 = parseExpr(&p, &val2, 0);
status = val0 ? stat1 : stat2;
val0 = val0 ? val1 : val2;
}
*v = val0;
*pp = p;
return status;
}
static MAC_ENTRY *evalExpr( MAC_HANDLE *handle, const char *expr )
{
MAC_ENTRY *entry = NULL;
int status;
const char* p = expr;
int value;
char valuestr[40];
char format[20] = "%d";
while (isspace((unsigned char)*p)) p++;
if (*p == '%')
{
int i = 1;
p++;
while (i < sizeof(format) && strchr(" #-+0", *p))
format[i++] = *p++;
while (i < sizeof(format) && strchr("0123456789", *p))
format[i++] = *p++;
if (i < sizeof(format) && strchr("diouxXc", *p))
{
format[i++] = *p++;
format[i] = 0;
}
else
return NULL;
}
status = parseExpr(&p, &value, 0);
if (status == DIVZERO)
printf ("macLib: division by zero\n");
if (status != SUCCESS)
return NULL;
while (isspace((unsigned char)*p)) p++;
if (*p)
{
printf("macLib: rubbish at end of expression: %s\n", p);
return NULL;
}
sprintf(valuestr, format, value);
entry = create( handle, expr, TRUE );
if ( entry )
{
entry->type = "calculation";
if ( rawval( handle, entry, valuestr ) == NULL )
return NULL;
}
return entry;
}
/*
* Look up macro entry with matching "special" attribute by name
*/
@@ -569,6 +749,10 @@ static MAC_ENTRY *lookup( MAC_HANDLE *handle, const char *name, int special )
printf( "lookup-> level = %d, name = %s, special = %d\n",
handle->level, name, special );
if ( (special == FALSE) ) {
entry = evalExpr( handle, name );
if (entry) return entry;
}
/* search backwards so scoping works */
for ( entry = last( handle ); entry != NULL; entry = previous( entry ) ) {
if ( entry->special != special )
@@ -688,6 +872,7 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, int level,
/* return immediately if raw value is NULL */
if ( *rawval == NULL ) return;
/* discard quotes and escapes if level is > 0 (i.e. if these aren't
the user's quotes and escapes) */
discard = ( level > 0 );

View File

@@ -0,0 +1,876 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* epicsThread.c */
/* Author: Marty Kraimer Date: 18JAN2000 */
/* This is a posix implementation of epicsThread */
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#define epicsExportSharedSymbols
#include "epicsStdio.h"
#include "ellLib.h"
#include "epicsEvent.h"
#include "epicsMutex.h"
#include "epicsString.h"
#include "epicsThread.h"
#include "cantProceed.h"
#include "errlog.h"
#include "epicsAssert.h"
#include "epicsExit.h"
static int mutexLock(pthread_mutex_t *id)
{
int status;
while(1) {
status = pthread_mutex_lock(id);
if(status!=EINTR) return status;
fprintf(stderr,"pthread_mutex_lock returned EINTR. Violates SUSv3\n");
}
}
#if defined DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
#endif
typedef struct commonAttr{
pthread_attr_t attr;
struct sched_param schedParam;
int maxPriority;
int minPriority;
int schedPolicy;
int usePolicy;
} commonAttr;
typedef struct epicsThreadOSD {
ELLNODE node;
pthread_t tid;
pid_t lwpId;
pthread_attr_t attr;
struct sched_param schedParam;
EPICSTHREADFUNC createFunc;
void *createArg;
epicsEventId suspendEvent;
int isSuspended;
int isEpicsThread;
int isFifoScheduled;
int isOnThreadList;
unsigned int osiPriority;
char *name;
} epicsThreadOSD;
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
typedef struct {
int min_pri, max_pri;
int policy;
int ok;
} priAvailable;
#endif
static pthread_key_t getpthreadInfo;
static pthread_mutex_t onceLock;
static pthread_mutex_t listLock;
static ELLLIST pthreadList = ELLLIST_INIT;
static commonAttr *pcommonAttr = 0;
static int epicsThreadOnceCalled = 0;
static epicsThreadOSD *createImplicit(void);
#define checkStatus(status,message) \
if((status)) {\
errlogPrintf("%s error %s\n",(message),strerror((status))); \
}
#define checkStatusQuit(status,message,method) \
if(status) { \
errlogPrintf("%s error %s\n",(message),strerror((status))); \
cantProceed((method)); \
}
/* The following are for use by once, which is only invoked from epicsThreadInit*/
/* Until epicsThreadInit completes errlogInit will not work */
/* It must also be used by init_threadInfo otherwise errlogInit could get */
/* called recursively */
#define checkStatusOnce(status,message) \
if((status)) {\
fprintf(stderr,"%s error %s\n",(message),strerror((status))); }
#define checkStatusOnceQuit(status,message,method) \
if(status) { \
fprintf(stderr,"%s error %s",(message),strerror((status))); \
fprintf(stderr," %s\n",method); \
fprintf(stderr,"epicsThreadInit cant proceed. Program exiting\n"); \
exit(-1);\
}
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
static int getOssPriorityValue(epicsThreadOSD *pthreadInfo)
{
double maxPriority,minPriority,slope,oss;
if(pcommonAttr->maxPriority==pcommonAttr->minPriority)
return(pcommonAttr->maxPriority);
maxPriority = (double)pcommonAttr->maxPriority;
minPriority = (double)pcommonAttr->minPriority;
slope = (maxPriority - minPriority)/100.0;
oss = (double)pthreadInfo->osiPriority * slope + minPriority;
return((int)oss);
}
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
static void setSchedulingPolicy(epicsThreadOSD *pthreadInfo,int policy)
{
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
int status;
if(!pcommonAttr->usePolicy) return;
status = pthread_attr_getschedparam(
&pthreadInfo->attr,&pthreadInfo->schedParam);
checkStatusOnce(status,"pthread_attr_getschedparam");
pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo);
status = pthread_attr_setschedpolicy(
&pthreadInfo->attr,policy);
checkStatusOnce(status,"pthread_attr_setschedpolicy");
status = pthread_attr_setschedparam(
&pthreadInfo->attr,&pthreadInfo->schedParam);
checkStatusOnce(status,"pthread_attr_setschedparam");
status = pthread_attr_setinheritsched(
&pthreadInfo->attr,PTHREAD_EXPLICIT_SCHED);
checkStatusOnce(status,"pthread_attr_setinheritsched");
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
}
static epicsThreadOSD * create_threadInfo(const char *name)
{
epicsThreadOSD *pthreadInfo;
pthreadInfo = callocMustSucceed(1,sizeof(*pthreadInfo),"create_threadInfo");
pthreadInfo->suspendEvent = epicsEventMustCreate(epicsEventEmpty);
pthreadInfo->name = epicsStrDup(name);
return pthreadInfo;
}
static epicsThreadOSD * init_threadInfo(const char *name,
unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm)
{
epicsThreadOSD *pthreadInfo;
int status;
pthreadInfo = create_threadInfo(name);
pthreadInfo->createFunc = funptr;
pthreadInfo->createArg = parm;
status = pthread_attr_init(&pthreadInfo->attr);
checkStatusOnce(status,"pthread_attr_init");
if(status) return 0;
status = pthread_attr_setdetachstate(
&pthreadInfo->attr, PTHREAD_CREATE_DETACHED);
checkStatusOnce(status,"pthread_attr_setdetachstate");
#if defined (_POSIX_THREAD_ATTR_STACKSIZE)
#if ! defined (OSITHREAD_USE_DEFAULT_STACK)
status = pthread_attr_setstacksize( &pthreadInfo->attr,(size_t)stackSize);
checkStatusOnce(status,"pthread_attr_setstacksize");
#endif /*OSITHREAD_USE_DEFAULT_STACK*/
#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
status = pthread_attr_setscope(&pthreadInfo->attr,PTHREAD_SCOPE_PROCESS);
if(errVerbose) checkStatusOnce(status,"pthread_attr_setscope");
pthreadInfo->osiPriority = priority;
return(pthreadInfo);
}
static void free_threadInfo(epicsThreadOSD *pthreadInfo)
{
int status;
status = mutexLock(&listLock);
checkStatusQuit(status,"pthread_mutex_lock","free_threadInfo");
if(pthreadInfo->isOnThreadList) ellDelete(&pthreadList,&pthreadInfo->node);
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","free_threadInfo");
epicsEventDestroy(pthreadInfo->suspendEvent);
status = pthread_attr_destroy(&pthreadInfo->attr);
checkStatusQuit(status,"pthread_attr_destroy","free_threadInfo");
free(pthreadInfo->name);
free(pthreadInfo);
}
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
/*
* The actually available range priority range (at least under linux)
* may be restricted by resource limitations (but that is ignored
* by sched_get_priority_max()). See bug #835138 which is fixed by
* this code.
*/
static int try_pri(int pri, int policy)
{
struct sched_param schedp;
schedp.sched_priority = pri;
return pthread_setschedparam(pthread_self(), policy, &schedp);
}
static void*
find_pri_range(void *arg)
{
priAvailable *prm = arg;
int min = sched_get_priority_min(prm->policy);
int max = sched_get_priority_max(prm->policy);
int low, try;
if ( -1 == min || -1 == max ) {
/* something is very wrong; maintain old behavior
* (warning message if sched_get_priority_xxx() fails
* and use default policy's sched_priority [even if
* that is likely to cause epicsThreadCreate to fail
* because that priority is not suitable for SCHED_FIFO]).
*/
prm->min_pri = prm->max_pri = -1;
return 0;
}
if ( try_pri(min, prm->policy) ) {
/* cannot create thread at minimum priority;
* probably no permission to use SCHED_FIFO
* at all. However, we still must return
* a priority range accepted by the SCHED_FIFO
* policy. Otherwise, epicsThreadCreate() cannot
* detect the unsufficient permission (EPERM)
* and fall back to a non-RT thread (because
* pthread_attr_setschedparam would fail with
* EINVAL due to the bad priority).
*/
prm->min_pri = prm->max_pri = min;
return 0;
}
/* Binary search through available priorities.
* The actually available range may be restricted
* by resource limitations (but that is ignored
* by sched_get_priority_max() [linux]).
*/
low = min;
while ( low < max ) {
try = (max+low)/2;
if ( try_pri(try, prm->policy) ) {
max = try;
} else {
low = try + 1;
}
}
prm->min_pri = min;
prm->max_pri = try_pri(max, prm->policy) ? max-1 : max;
prm->ok = 1;
return 0;
}
static void findPriorityRange(commonAttr *a_p)
{
priAvailable arg;
pthread_t id;
void *dummy;
int status;
arg.policy = a_p->schedPolicy;
arg.ok = 0;
status = pthread_create(&id, 0, find_pri_range, &arg);
checkStatusQuit(status, "pthread_create","epicsThreadInit");
status = pthread_join(id, &dummy);
checkStatusQuit(status, "pthread_join","epicsThreadInit");
a_p->minPriority = arg.min_pri;
a_p->maxPriority = arg.max_pri;
a_p->usePolicy = arg.ok;
}
#endif
static void once(void)
{
epicsThreadOSD *pthreadInfo;
int status;
pthread_key_create(&getpthreadInfo,0);
status = pthread_mutex_init(&onceLock,0);
checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
status = pthread_mutex_init(&listLock,0);
checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
pcommonAttr = calloc(1,sizeof(commonAttr));
if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","epicsThreadInit");
status = pthread_attr_init(&pcommonAttr->attr);
checkStatusOnceQuit(status,"pthread_attr_init","epicsThreadInit");
status = pthread_attr_setdetachstate(
&pcommonAttr->attr, PTHREAD_CREATE_DETACHED);
checkStatusOnce(status,"pthread_attr_setdetachstate");
status = pthread_attr_setscope(&pcommonAttr->attr,PTHREAD_SCOPE_PROCESS);
if(errVerbose) checkStatusOnce(status,"pthread_attr_setscope");
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
status = pthread_attr_setschedpolicy(
&pcommonAttr->attr,SCHED_FIFO);
checkStatusOnce(status,"pthread_attr_setschedpolicy");
status = pthread_attr_getschedpolicy(
&pcommonAttr->attr,&pcommonAttr->schedPolicy);
checkStatusOnce(status,"pthread_attr_getschedpolicy");
status = pthread_attr_getschedparam(
&pcommonAttr->attr,&pcommonAttr->schedParam);
checkStatusOnce(status,"pthread_attr_getschedparam");
findPriorityRange(pcommonAttr);
if(pcommonAttr->maxPriority == -1) {
pcommonAttr->maxPriority = pcommonAttr->schedParam.sched_priority;
fprintf(stderr,"sched_get_priority_max failed set to %d\n",
pcommonAttr->maxPriority);
}
if(pcommonAttr->minPriority == -1) {
pcommonAttr->minPriority = pcommonAttr->schedParam.sched_priority;
fprintf(stderr,"sched_get_priority_min failed set to %d\n",
pcommonAttr->maxPriority);
}
#else
if(errVerbose) fprintf(stderr,"task priorities are not implemented\n");
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
pthreadInfo = init_threadInfo("_main_",0,epicsThreadGetStackSize(epicsThreadStackSmall),0,0);
pthreadInfo->lwpId = syscall(SYS_gettid);
status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo);
checkStatusOnceQuit(status,"pthread_setspecific","epicsThreadInit");
status = mutexLock(&listLock);
checkStatusQuit(status,"pthread_mutex_lock","epicsThreadInit");
ellAdd(&pthreadList,&pthreadInfo->node);
pthreadInfo->isOnThreadList = 1;
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadInit");
status = atexit(epicsExitCallAtExits);
checkStatusOnce(status,"atexit");
epicsThreadOnceCalled = 1;
}
static void * start_routine(void *arg)
{
epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg;
int status;
sigset_t blockAllSig;
char comm[16];
/* Set the name of the thread's process. Limited to 16 characters. */
snprintf(comm, sizeof(comm), "%s", pthreadInfo->name);
prctl(PR_SET_NAME, comm, 0l, 0l, 0l);
pthreadInfo->lwpId = syscall(SYS_gettid);
sigfillset(&blockAllSig);
pthread_sigmask(SIG_SETMASK,&blockAllSig,NULL);
status = pthread_setspecific(getpthreadInfo,arg);
checkStatusQuit(status,"pthread_setspecific","start_routine");
status = mutexLock(&listLock);
checkStatusQuit(status,"pthread_mutex_lock","start_routine");
ellAdd(&pthreadList,&pthreadInfo->node);
pthreadInfo->isOnThreadList = 1;
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","start_routine");
(*pthreadInfo->createFunc)(pthreadInfo->createArg);
epicsExitCallAtThreadExits ();
free_threadInfo(pthreadInfo);
return(0);
}
static void epicsThreadInit(void)
{
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
int status = pthread_once(&once_control,once);
checkStatusQuit(status,"pthread_once","epicsThreadInit");
}
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
{
#if ! defined (_POSIX_THREAD_ATTR_STACKSIZE)
return 0;
#elif defined (OSITHREAD_USE_DEFAULT_STACK)
return 0;
#else
#define STACK_SIZE(f) (f * 0x10000 * sizeof(void *))
static const unsigned stackSizeTable[epicsThreadStackBig+1] = {
STACK_SIZE(1), STACK_SIZE(2), STACK_SIZE(4)
};
if (stackSizeClass<epicsThreadStackSmall) {
errlogPrintf("epicsThreadGetStackSize illegal argument (too small)");
return stackSizeTable[epicsThreadStackBig];
}
if (stackSizeClass>epicsThreadStackBig) {
errlogPrintf("epicsThreadGetStackSize illegal argument (too large)");
return stackSizeTable[epicsThreadStackBig];
}
return stackSizeTable[stackSizeClass];
#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/
}
epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg)
{
static struct epicsThreadOSD threadOnceComplete;
#define EPICS_THREAD_ONCE_DONE &threadOnceComplete
int status;
epicsThreadInit();
status = mutexLock(&onceLock);
if(status) {
fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
strerror(status));
exit(-1);
}
if (*id != EPICS_THREAD_ONCE_DONE) {
if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
*id = epicsThreadGetIdSelf(); /* mark active */
status = pthread_mutex_unlock(&onceLock);
checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
func(arg);
status = mutexLock(&onceLock);
checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
*id = EPICS_THREAD_ONCE_DONE; /* mark done */
} else if (*id == epicsThreadGetIdSelf()) {
status = pthread_mutex_unlock(&onceLock);
checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
cantProceed("Recursive epicsThreadOnce() initialization\n");
} else
while (*id != EPICS_THREAD_ONCE_DONE) {
/* Another thread is in the above func(arg) call. */
status = pthread_mutex_unlock(&onceLock);
checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
epicsThreadSleep(epicsThreadSleepQuantum());
status = mutexLock(&onceLock);
checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
}
}
status = pthread_mutex_unlock(&onceLock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
}
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
unsigned int priority, unsigned int stackSize,
EPICSTHREADFUNC funptr,void *parm)
{
epicsThreadOSD *pthreadInfo;
int status;
sigset_t blockAllSig, oldSig;
epicsThreadInit();
assert(pcommonAttr);
sigfillset(&blockAllSig);
pthread_sigmask(SIG_SETMASK,&blockAllSig,&oldSig);
pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm);
if(pthreadInfo==0) return 0;
pthreadInfo->isEpicsThread = 1;
setSchedulingPolicy(pthreadInfo,SCHED_FIFO);
pthreadInfo->isFifoScheduled = 1;
status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr,
start_routine,pthreadInfo);
if(status==EPERM){
/* Try again without SCHED_FIFO*/
free_threadInfo(pthreadInfo);
pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm);
if(pthreadInfo==0) return 0;
pthreadInfo->isEpicsThread = 1;
status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr,
start_routine,pthreadInfo);
}
checkStatusOnce(status,"pthread_create");
if(status) {
free_threadInfo(pthreadInfo);
return 0;
}
status = pthread_sigmask(SIG_SETMASK,&oldSig,NULL);
checkStatusOnce(status,"pthread_sigmask");
return(pthreadInfo);
}
/*
* Cleanup routine for threads not created by epicsThreadCreate().
*/
/* static void nonEPICSthreadCleanup(void *arg)
{
epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg;
free(pthreadInfo->name);
free(pthreadInfo);
} */
/*
* Create dummy context for threads not created by epicsThreadCreate().
*/
static epicsThreadOSD *createImplicit(void)
{
epicsThreadOSD *pthreadInfo;
char name[64];
pthread_t tid;
int status;
tid = pthread_self();
sprintf(name, "non-EPICS_%ld", (long)tid);
pthreadInfo = create_threadInfo(name);
pthreadInfo->tid = tid;
pthreadInfo->osiPriority = 0;
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
{
struct sched_param param;
int policy;
if(pthread_getschedparam(tid,&policy,&param) == 0)
pthreadInfo->osiPriority =
(param.sched_priority - pcommonAttr->minPriority) * 100.0 /
(pcommonAttr->maxPriority - pcommonAttr->minPriority + 1);
}
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo);
checkStatusQuit(status,"pthread_setspecific","createImplicit");
/* pthread_cleanup_push(nonEPICSthreadCleanup, pthreadInfo); */
return pthreadInfo;
}
epicsShareFunc void epicsShareAPI epicsThreadSuspendSelf(void)
{
epicsThreadOSD *pthreadInfo;
epicsThreadInit();
pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
if(pthreadInfo==NULL)
pthreadInfo = createImplicit();
pthreadInfo->isSuspended = 1;
epicsEventMustWait(pthreadInfo->suspendEvent);
}
epicsShareFunc void epicsShareAPI epicsThreadResume(epicsThreadOSD *pthreadInfo)
{
assert(epicsThreadOnceCalled);
pthreadInfo->isSuspended = 0;
epicsEventSignal(pthreadInfo->suspendEvent);
}
epicsShareFunc void epicsShareAPI epicsThreadExitMain(void)
{
epicsThreadOSD *pthreadInfo;
epicsThreadInit();
pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
if(pthreadInfo==NULL)
pthreadInfo = createImplicit();
if(pthreadInfo->createFunc) {
errlogPrintf("called from non-main thread\n");
cantProceed("epicsThreadExitMain");
}
else {
free_threadInfo(pthreadInfo);
pthread_exit(0);
}
}
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPriority(epicsThreadId pthreadInfo)
{
assert(epicsThreadOnceCalled);
return(pthreadInfo->osiPriority);
}
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPrioritySelf(void)
{
epicsThreadInit();
return(epicsThreadGetPriority(epicsThreadGetIdSelf()));
}
epicsShareFunc void epicsShareAPI epicsThreadSetPriority(epicsThreadId pthreadInfo,unsigned int priority)
{
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
int status;
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
assert(epicsThreadOnceCalled);
assert(pthreadInfo);
if(!pthreadInfo->isEpicsThread) {
fprintf(stderr,"epicsThreadSetPriority called by non epics thread\n");
return;
}
pthreadInfo->osiPriority = priority;
if(!pthreadInfo->isFifoScheduled) return;
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
if(!pcommonAttr->usePolicy) return;
pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo);
status = pthread_attr_setschedparam(
&pthreadInfo->attr,&pthreadInfo->schedParam);
if(errVerbose) checkStatus(status,"pthread_attr_setschedparam");
status = pthread_setschedparam(
pthreadInfo->tid,pcommonAttr->schedPolicy,&pthreadInfo->schedParam);
if(errVerbose) checkStatus(status,"pthread_setschedparam");
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
}
epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadHighestPriorityLevelBelow(
unsigned int priority, unsigned *pPriorityJustBelow)
{
unsigned newPriority = priority - 1;
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
int diff;
diff = pcommonAttr->maxPriority - pcommonAttr->minPriority;
if(diff<0) diff = -diff;
if(diff>1 && diff <100) newPriority -= 100/(diff+1);
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
if (newPriority <= 99) {
*pPriorityJustBelow = newPriority;
return epicsThreadBooleanStatusSuccess;
}
return epicsThreadBooleanStatusFail;
}
epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadLowestPriorityLevelAbove(
unsigned int priority, unsigned *pPriorityJustAbove)
{
unsigned newPriority = priority + 1;
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
int diff;
diff = pcommonAttr->maxPriority - pcommonAttr->minPriority;
if(diff<0) diff = -diff;
if(diff>1 && diff <100) newPriority += 100/(diff+1);
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
if (newPriority <= 99) {
*pPriorityJustAbove = newPriority;
return epicsThreadBooleanStatusSuccess;
}
return epicsThreadBooleanStatusFail;
}
epicsShareFunc int epicsShareAPI epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2)
{
assert(epicsThreadOnceCalled);
assert(p1);
assert(p2);
return(pthread_equal(p1->tid,p2->tid));
}
epicsShareFunc int epicsShareAPI epicsThreadIsSuspended(epicsThreadId pthreadInfo) {
assert(epicsThreadOnceCalled);
assert(pthreadInfo);
return(pthreadInfo->isSuspended ? 1 : 0);
}
epicsShareFunc void epicsShareAPI epicsThreadSleep(double seconds)
{
struct timespec delayTime;
struct timespec remainingTime;
double nanoseconds;
if (seconds > 0) {
delayTime.tv_sec = seconds;
nanoseconds = (seconds - delayTime.tv_sec) *1e9;
delayTime.tv_nsec = nanoseconds;
}
else {
delayTime.tv_sec = 0;
delayTime.tv_nsec = 0;
}
while (nanosleep(&delayTime, &remainingTime) == -1 &&
errno == EINTR)
delayTime = remainingTime;
}
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf(void) {
epicsThreadOSD *pthreadInfo;
epicsThreadInit();
pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
if(pthreadInfo==NULL)
pthreadInfo = createImplicit();
assert ( pthreadInfo );
return(pthreadInfo);
}
epicsShareFunc pthread_t epicsShareAPI epicsThreadGetPosixThreadId ( epicsThreadId threadId )
{
return threadId->tid;
}
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetId(const char *name) {
epicsThreadOSD *pthreadInfo;
int status;
assert(epicsThreadOnceCalled);
status = mutexLock(&listLock);
checkStatusQuit(status,"pthread_mutex_lock","epicsThreadGetId");
pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
while(pthreadInfo) {
if(strcmp(name,pthreadInfo->name) == 0) break;
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadGetId");
return(pthreadInfo);
}
epicsShareFunc const char epicsShareAPI *epicsThreadGetNameSelf()
{
epicsThreadOSD *pthreadInfo;
epicsThreadInit();
pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
if(pthreadInfo==NULL)
pthreadInfo = createImplicit();
return(pthreadInfo->name);
}
epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size)
{
assert(epicsThreadOnceCalled);
strncpy(name, pthreadInfo->name, size-1);
name[size-1] = '\0';
}
static void showThreadInfo(epicsThreadOSD *pthreadInfo,unsigned int level)
{
if(!pthreadInfo) {
fprintf(epicsGetStdout()," NAME EPICS ID "
"LWP ID OSIPRI OSSPRI STATE\n");
} else {
struct sched_param param;
int policy;
int priority = 0;
if(pthreadInfo->tid) {
int status;
status = pthread_getschedparam(pthreadInfo->tid,&policy,&param);
if(!status) priority = param.sched_priority;
}
fprintf(epicsGetStdout(),"%16.16s %18p %8lu %3d%8d %8.8s\n",
pthreadInfo->name,(void *)
pthreadInfo,(unsigned long)pthreadInfo->lwpId,
pthreadInfo->osiPriority,priority,
pthreadInfo->isSuspended?"SUSPEND":"OK");
}
}
epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level)
{
epicsThreadOSD *pthreadInfo;
int status;
epicsThreadInit();
epicsThreadShow(0,level);
status = mutexLock(&listLock);
checkStatusQuit(status,"pthread_mutex_lock","epicsThreadShowAll");
pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
while(pthreadInfo) {
showThreadInfo(pthreadInfo,level);
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadShowAll");
}
epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsigned int level)
{
epicsThreadOSD *pthreadInfo;
int status;
int found = 0;
epicsThreadInit();
if(!showThread) {
showThreadInfo(0,level);
return;
}
status = mutexLock(&listLock);
checkStatusQuit(status,"pthread_mutex_lock","epicsThreadShowAll");
pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
while(pthreadInfo) {
if (((epicsThreadId)pthreadInfo == showThread)
|| ((epicsThreadId)pthreadInfo->tid == showThread)) {
found = 1;
showThreadInfo(pthreadInfo,level);
}
pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
}
status = pthread_mutex_unlock(&listLock);
checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadShowAll");
if (!found)
printf("Thread %#lx (%lu) not found.\n", (unsigned long)showThread, (unsigned long)showThread);
}
epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void)
{
pthread_key_t *key;
int status;
epicsThreadInit();
key = callocMustSucceed(1,sizeof(pthread_key_t),"epicsThreadPrivateCreate");
status = pthread_key_create(key,0);
checkStatusQuit(status,"pthread_key_create","epicsThreadPrivateCreate");
return((epicsThreadPrivateId)key);
}
epicsShareFunc void epicsShareAPI epicsThreadPrivateDelete(epicsThreadPrivateId id)
{
pthread_key_t *key = (pthread_key_t *)id;
int status;
assert(epicsThreadOnceCalled);
status = pthread_key_delete(*key);
checkStatusQuit(status,"pthread_key_delete","epicsThreadPrivateDelete");
free((void *)key);
}
epicsShareFunc void epicsShareAPI epicsThreadPrivateSet (epicsThreadPrivateId id, void *value)
{
pthread_key_t *key = (pthread_key_t *)id;
int status;
assert(epicsThreadOnceCalled);
if(errVerbose && !value)
errlogPrintf("epicsThreadPrivateSet: setting value of 0\n");
status = pthread_setspecific(*key,value);
checkStatusQuit(status,"pthread_setspecific","epicsThreadPrivateSet");
}
epicsShareFunc void epicsShareAPI *epicsThreadPrivateGet(epicsThreadPrivateId id)
{
pthread_key_t *key = (pthread_key_t *)id;
assert(epicsThreadOnceCalled);
return pthread_getspecific(*key);
}
epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum ()
{
double hz;
hz = sysconf ( _SC_CLK_TCK );
return 1.0 / hz;
}

View File

@@ -110,7 +110,22 @@ static long vxDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *
static void *devA24Malloc(size_t size);
static void devA24Free(void *pBlock);
static long devInit(void) { return 0;}
static int (*sysIntEnableFunc)(int) = NULL;
static int (*sysIntDisableFunc)(int) = NULL;
static int (*sysIntEnablePICFunc)(int) = NULL;
static int (*sysIntDisablePICFunc)(int) = NULL;
static long devInit(void)
{
/* We don't know which functions are implemented in the BSP */
sysIntEnableFunc = epicsFindSymbol ("sysIntEnable");
sysIntDisableFunc = epicsFindSymbol ("sysIntDisable");
sysIntDisablePICFunc = epicsFindSymbol ("sysIntDisablePIC");
sysIntEnablePICFunc = epicsFindSymbol ("sysIntEnablePIC");
return 0;
}
static long vxDevConnectInterruptVME (
unsigned vectorNumber,
@@ -214,16 +229,8 @@ static long vxDevDisconnectInterruptVME (
*/
static long vxDevEnableInterruptLevelVME (unsigned level)
{
# if CPU_FAMILY != I80X86
int s;
s = sysIntEnable (level);
if (s!=OK) {
return S_dev_intEnFail;
}
return 0;
# else
return S_dev_intEnFail;
# endif
if (!sysIntEnableFunc) return S_dev_intEnFail;
return sysIntEnableFunc (level) == OK ? 0 : S_dev_intEnFail;
}
/*
@@ -231,16 +238,8 @@ static long vxDevEnableInterruptLevelVME (unsigned level)
*/
long devEnableInterruptLevelISA (unsigned level)
{
# if CPU_FAMILY == I80X86
int s;
s = sysIntEnablePIC (level);
if (s!=OK) {
return S_dev_intEnFail;
}
return 0;
# else
return S_dev_intEnFail;
# endif
if (!sysIntEnablePICFunc) return S_dev_intEnFail;
return sysIntEnablePICFunc (level) == OK ? 0 : S_dev_intEnFail;
}
/*
@@ -248,17 +247,8 @@ long devEnableInterruptLevelISA (unsigned level)
*/
long devDisableInterruptLevelISA (unsigned level)
{
# if CPU_FAMILY == I80X86
int s;
s = sysIntDisablePIC (level);
if (s!=OK) {
return S_dev_intEnFail;
}
# else
return S_dev_intEnFail;
# endif
return 0;
if (!sysIntDisablePICFunc) return S_dev_intDissFail;
return sysIntDisablePICFunc (level) == OK ? 0 : S_dev_intDissFail;
}
/*
@@ -266,16 +256,8 @@ long devDisableInterruptLevelISA (unsigned level)
*/
static long vxDevDisableInterruptLevelVME (unsigned level)
{
# if CPU_FAMILY != I80X86
int s;
s = sysIntDisable (level);
if (s!=OK) {
return S_dev_intDissFail;
}
return 0;
# else
return S_dev_intEnFail;
# endif
if (!sysIntDisableFunc) return S_dev_intDissFail;
return sysIntDisableFunc (level) == OK ? 0 : S_dev_intDissFail;
}
/*

View File

@@ -176,7 +176,7 @@ recordtype(ai) {
pp(TRUE)
interest(2)
}
field(ROFF,DBF_ULONG) {
field(ROFF,DBF_LONG) {
prompt("Raw Offset")
pp(TRUE)
interest(2)

View File

@@ -82,7 +82,7 @@ recordtype(ao) {
interest(1)
size(16)
}
field(ROFF,DBF_ULONG) {
field(ROFF,DBF_LONG) {
prompt("Raw Offset")
pp(TRUE)
interest(2)

27
startup/win64.bat Normal file
View File

@@ -0,0 +1,27 @@
@ECHO OFF
REM *************************************************************************
REM Copyright (c) 2002 The University of Chicago, as Operator of Argonne
REM National Laboratory.
REM Copyright (c) 2002 The Regents of the University of California, as
REM Operator of Los Alamos National Laboratory.
REM EPICS BASE Versions 3.13.7
REM and higher are distributed subject to a Software License Agreement found
REM in file LICENSE that is included with this distribution.
set PATH=%PATH%;C:\cygwin\bin
REM --------------- Visual c++ ------------------------
call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" amd64
REM --------------- CUDA -----------------------------
REM --------------- EPICS -----------------------------
REM -- R3.14 requirements
set EPICS_HOST_ARCH=windows-x64
set PATH=%PATH%;C:\epics\base-3.14.12.4\bin\%EPICS_HOST_ARCH%
REM ===================================================
REM ====== OPTIONAL ENVIRONMENT VARIABLES FOLLOW ======
REM ---------------- EPICS tools ----------------------
REM -- HOST_ARCH needed for Makefile.Host builds --
set HOST_ARCH=WIN32