From d16b7ddfb97b07f8e1a130255b00c052d624420e Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Fri, 28 Jan 2000 02:24:14 +0000 Subject: [PATCH] renamed files --- src/libCom/osi/os/RTEMS/osdInterrupt.c | 87 ++++ src/libCom/osi/os/RTEMS/osdInterrupt.h | 11 + src/libCom/osi/os/RTEMS/osdSem.c | 191 ++++++++ src/libCom/osi/os/RTEMS/osdThread.c | 407 ++++++++++++++++++ src/libCom/osi/os/default/osdAssert.c | 82 ++++ .../osi/os/default/osdFindGlobalSymbol.c | 6 + .../osi/os/default/osdFindGlobalSymbol.h | 5 + src/libCom/osi/os/default/osdInterrupt.c | 47 ++ src/libCom/osi/os/default/osdInterrupt.h | 5 + src/libCom/osi/os/default/osdPoolStatus.c | 14 + src/libCom/osi/os/default/osdPoolStatus.h | 5 + src/libCom/osi/os/default/osdRing.c | 190 ++++++++ src/libCom/osi/os/default/osdRing.h | 5 + src/libCom/osi/os/default/osdSigPipeIgnore.c | 11 + src/libCom/osi/os/default/osdSigPipeIgnore.h | 5 + src/libCom/osi/os/posix/osdSem.c | 237 ++++++++++ src/libCom/osi/os/posix/osdSem.h | 1 + src/libCom/osi/os/posix/osdSigPipeIgnore.c | 80 ++++ src/libCom/osi/os/posix/osdSigPipeIgnore.h | 7 + src/libCom/osi/os/posix/osdThread.c | 225 ++++++++++ src/libCom/osi/os/posix/osdThread.h | 5 + src/libCom/osi/os/posix/osdTime.cpp | 51 +++ src/libCom/osi/os/posix/osdTime.h | 26 ++ 23 files changed, 1703 insertions(+) create mode 100644 src/libCom/osi/os/RTEMS/osdInterrupt.c create mode 100644 src/libCom/osi/os/RTEMS/osdInterrupt.h create mode 100644 src/libCom/osi/os/RTEMS/osdSem.c create mode 100644 src/libCom/osi/os/RTEMS/osdThread.c create mode 100644 src/libCom/osi/os/default/osdAssert.c create mode 100644 src/libCom/osi/os/default/osdFindGlobalSymbol.c create mode 100644 src/libCom/osi/os/default/osdFindGlobalSymbol.h create mode 100644 src/libCom/osi/os/default/osdInterrupt.c create mode 100644 src/libCom/osi/os/default/osdInterrupt.h create mode 100644 src/libCom/osi/os/default/osdPoolStatus.c create mode 100644 src/libCom/osi/os/default/osdPoolStatus.h create mode 100644 src/libCom/osi/os/default/osdRing.c create mode 100644 src/libCom/osi/os/default/osdRing.h create mode 100644 src/libCom/osi/os/default/osdSigPipeIgnore.c create mode 100644 src/libCom/osi/os/default/osdSigPipeIgnore.h create mode 100644 src/libCom/osi/os/posix/osdSem.c create mode 100644 src/libCom/osi/os/posix/osdSem.h create mode 100644 src/libCom/osi/os/posix/osdSigPipeIgnore.c create mode 100644 src/libCom/osi/os/posix/osdSigPipeIgnore.h create mode 100644 src/libCom/osi/os/posix/osdThread.c create mode 100644 src/libCom/osi/os/posix/osdThread.h create mode 100644 src/libCom/osi/os/posix/osdTime.cpp create mode 100644 src/libCom/osi/os/posix/osdTime.h diff --git a/src/libCom/osi/os/RTEMS/osdInterrupt.c b/src/libCom/osi/os/RTEMS/osdInterrupt.c new file mode 100644 index 000000000..dbdd2e8a7 --- /dev/null +++ b/src/libCom/osi/os/RTEMS/osdInterrupt.c @@ -0,0 +1,87 @@ +/* + * RTEMS osiInterrupt.c + * $Id$ + * Author: W. Eric Norum + * eric@cls.usask.ca + * (306) 966-6055 + */ + +#include +#include +#include +#include "errlog.h" + +#define INTERRUPT_CONTEXT_MESSAGE_QUEUE_COUNT 100 + +static rtems_id interruptContextMessageQueue; + +int +interruptLock (void) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable (level); + return level; +} + +void +interruptUnlock (int key) +{ + rtems_interrupt_level level = key; + + rtems_interrupt_enable (level); +} + +int +interruptIsInterruptContext (void) +{ + return rtems_interrupt_is_in_progress (); +} + +/* + * Pass a message from an interrupt context. + * Note that this passes a pointer to the message, not the message itself. + * This implies that the message must remain valid after the + * interrupt context is no longer active. + */ +void +interruptContextMessage (const char *message) +{ + rtems_message_queue_send (interruptContextMessageQueue, &message, sizeof message); +} + +/* + * Daemon to process interrupt context messages + */ +rtems_task +InterruptContextMessageDaemon (rtems_task_argument arg) +{ + const char *message; + rtems_unsigned32 size; + rtems_status_code sc; + + sc = rtems_message_queue_create (rtems_build_name ('I', 'C', 'M', 'Q'), + INTERRUPT_CONTEXT_MESSAGE_QUEUE_COUNT, + sizeof message, + RTEMS_FIFO | RTEMS_LOCAL, + &interruptContextMessageQueue); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf ("Can't create interrupt context message queue: %s\n", rtems_status_text (sc)); + rtems_task_suspend (RTEMS_SELF); + } + for (;;) { + sc = rtems_message_queue_receive (interruptContextMessageQueue, + &message, + &size, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf ("Can't receive message from interrupt context: %s\n", rtems_status_text (sc)); + rtems_task_suspend (RTEMS_SELF); + } + if (size == sizeof message) + syslog (LOG_ERR, "%s", message); + else + errlogPrintf ("Received %d-byte message from interrupt context", size); + } +} diff --git a/src/libCom/osi/os/RTEMS/osdInterrupt.h b/src/libCom/osi/os/RTEMS/osdInterrupt.h new file mode 100644 index 000000000..e3902ba4d --- /dev/null +++ b/src/libCom/osi/os/RTEMS/osdInterrupt.h @@ -0,0 +1,11 @@ +/* + * RTEMS osiInterrupt.h + * $Id$ + * Author: W. Eric Norum + * eric@cls.usask.ca + * (306) 966-6055 + */ +int interruptLock (void); +void interruptUnlock (int key); +int interruptIsInterruptContext (void); +void interruptContextMessage (const char *message); diff --git a/src/libCom/osi/os/RTEMS/osdSem.c b/src/libCom/osi/os/RTEMS/osdSem.c new file mode 100644 index 000000000..1ea36146b --- /dev/null +++ b/src/libCom/osi/os/RTEMS/osdSem.c @@ -0,0 +1,191 @@ +/* + * RTEMS osiSem.c + * $Id$ + * Author: W. Eric Norum + * eric@cls.usask.ca + * (306) 966-6055 + */ + +#include +#include +#include + +#include "osiSem.h" +#include "errlog.h" + +/* + * Create a simple binary semaphore + */ +semId +semBinaryCreate(int initialState) +{ + rtems_status_code sc; + rtems_id sid; + rtems_interrupt_level level; + static char c1 = 'a'; + static char c2 = 'a'; + + sc = rtems_semaphore_create (rtems_build_name ('S', 'B', c2, c1), + initialState, + RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, + 0, + &sid); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf ("Can't create binary semaphore: %s\n", rtems_status_text (sc)); + return NULL; + } + rtems_interrupt_disable (level); + if (c1 == 'z') { + if (c2 == 'z') + c2 = 'a'; + else + c2++; + c1 = 'a'; + } + else { + c1++; + } + rtems_interrupt_enable (level); + return (semId)sid; +} + +semId +semBinaryMustCreate(int initialState) +{ + semId sid; + + if ((sid = semBinaryCreate (initialState)) == NULL) + cantProceed ("Can't create binary semaphore"); + return sid; +} + +void +semBinaryDestroy(semId id) +{ + rtems_id sid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_semaphore_delete (sid); + if (sc != RTEMS_SUCCESSFUL) + errlogPrintf ("Can't destroy semaphore: %s\n", rtems_status_text (sc)); +} + +void +semBinaryGive(semId id) +{ + rtems_id sid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_semaphore_release (sid); + if (sc != RTEMS_SUCCESSFUL) + errlogPrintf ("Can't release semaphore: %s\n", rtems_status_text (sc)); +} + +semTakeStatus +semBinaryTake(semId id) +{ + rtems_id sid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + return semTakeError; + return semTakeOK; +} + +void +semBinaryMustTake(semId id) +{ + rtems_id sid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf ("Can't obtain semaphore: %s\n", rtems_status_text (sc)); + assert (sc == RTEMS_SUCCESSFUL); + } +} + +semTakeStatus +semBinaryTakeTimeout(semId id, double timeOut) +{ + rtems_id sid = (rtems_id)id; + rtems_status_code sc; + rtems_interval delay; + extern double rtemsTicksPerSecond_double; + + delay = timeOut * rtemsTicksPerSecond_double; + if (delay == 0) + delay = 1; + sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, delay); + if (sc == RTEMS_SUCCESSFUL) + return semTakeOK; + else if (sc == RTEMS_TIMEOUT) + return semTakeTimeout; + else + return semTakeError; +} + +semTakeStatus +semBinaryTakeNoWait(semId id) +{ + rtems_id sid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_semaphore_obtain (sid, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT); + if (sc == RTEMS_SUCCESSFUL) + return semTakeOK; + else if (sc == RTEMS_TIMEOUT) + return semTakeTimeout; + else + return semTakeError; +} + +void +semBinaryShow(semId id) +{ +} + +semId +semMutexCreate(void) +{ + rtems_status_code sc; + rtems_id sid; + rtems_interrupt_level level; + static char c1 = 'a'; + static char c2 = 'a'; + + sc = rtems_semaphore_create (rtems_build_name ('S', 'M', c2, c1), + 1, + RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE|RTEMS_INHERIT_PRIORITY |RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL, + 0, + &sid); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf ("Can't create mutex semaphore: %s\n", rtems_status_text (sc)); + return NULL; + } + rtems_interrupt_disable (level); + if (c1 == 'z') { + if (c2 == 'z') + c2 = 'a'; + else + c2++; + c1 = 'a'; + } + else { + c1++; + } + rtems_interrupt_enable (level); + return (semId)sid; +} + +semId +semMutexMustCreate(void) +{ + semId sid; + + if ((sid = semMutexCreate) == NULL) + cantProceed ("Can't create mutex semaphore"); + return sid; +} diff --git a/src/libCom/osi/os/RTEMS/osdThread.c b/src/libCom/osi/os/RTEMS/osdThread.c new file mode 100644 index 000000000..9f7f7ea8f --- /dev/null +++ b/src/libCom/osi/os/RTEMS/osdThread.c @@ -0,0 +1,407 @@ +/* + * RTEMS osiThread.c + * $Id$ + * Author: W. Eric Norum + * eric@cls.usask.ca + * (306) 966-6055 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "errlog.h" +#include "ellLib.h" +#include "osiThread.h" +#include "cantProceed.h" + +/* + * This is one place where RTEMS needs a lot of help to implement + * the EPICS operating-system-specific routines. + * 1) RTEMS task names are at most 4 characters long. This is solved + * by using a binary tree (AVL) to map long task names to RTEMS + * task I.D. numbers. + * 2) RTEMS has no notion of task safe/unsafe states. The solution + * here is to add a semaphore which must be held before a task + * can be deleted. + * 3) RTEMS tasks do not destroy themselves when the entry function + * returns. A simple wrapper function fixes this problem + */ + +/* + * Per-task variables + */ +struct taskVars { + char *name; + THREADFUNC funptr; + void *parm; + rtems_id taskSafeSemaphore; + rtems_id tid; +}; + +/* + * RTEMS task notepad assignments + */ +#define TASK_VARIABLE_NOTE_INDEX 12 + +/* + * Thread name lookup + */ +static rtems_id nameTableMutex; +static avl_tree *nameTable; + +static int +compare_names (const void *a, const void *b, void *param) +{ + const struct taskVars *da = a, *db = b; + int i; + + if ((i = db->name[0] - da->name[0]) == 0) + return strcmp (da->name, db->name); + return i; +} + +void +rtems_epics_task_init (void) +{ + rtems_status_code sc; + + sc = rtems_semaphore_create ( + rtems_build_name ('T', 'H', 'S', 'H'), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &nameTableMutex); + if (sc != RTEMS_SUCCESSFUL) + rtems_panic ("No nametable mutex"); + nameTable = avl_create (compare_names, NULL); +} + +static rtems_id +tid_for_name (const char *name) +{ + struct taskVars entry, *e; + rtems_id tid = 0; + + rtems_semaphore_obtain (nameTableMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + entry.name = (char *)name; + e = avl_find (nameTable, &entry); + if (e) + tid = e->tid; + rtems_semaphore_release (nameTableMutex); + return tid; +} + +/* Just map osi 0 to 99 into RTEMS 199 to 100 */ +/* For RTEMS lower number means higher priority */ +/* RTEMS = 100 + (99 - osi) = 199 - osi */ +/* osi = 199 - RTEMS */ +int threadGetOsiPriorityValue(int ossPriority) +{ + return (199 - ossPriority); +} + +int threadGetOssPriorityValue(int osiPriority) +{ + return (199 - osiPriority); +} + +#define ARCH_STACK_FACTOR 2 + +unsigned int +threadGetStackSize (threadStackSizeClass size) +{ + switch(size) { + case threadStackSmall: return( 4000*ARCH_STACK_FACTOR); + case threadStackMedium: return( 6000*ARCH_STACK_FACTOR); + case threadStackBig: return(11000*ARCH_STACK_FACTOR); + default: + errlogPrintf("threadGetStackSize illegal argument"); + } + return(11000*ARCH_STACK_FACTOR); +} + +/* + * The task wrapper + */ +static rtems_task +threadWrapper (rtems_task_argument arg) +{ + struct taskVars *v = (struct taskVars *)arg; + + (*v->funptr)(v->parm); + threadDestroy (threadGetIdSelf ()); +} + +/* + * Create and start a new thread + */ +threadId +threadCreate (const char *name, + unsigned int priority, unsigned int stackSize, + THREADFUNC funptr,void *parm) +{ + struct taskVars *v; + rtems_id tid, safe; + rtems_status_code sc; + char c[4]; + static volatile int initialized; + + if (!initialized) { + rtems_mode mode; + + rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &mode); + if (!initialized) { + rtems_epics_task_init (); + initialized = 1; + } + rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode); + } + + if (stackSize < RTEMS_MINIMUM_STACK_SIZE) { + errlogPrintf ("threadCreate %s illegal stackSize %d\n",name,stackSize); + return 0; + } + strncpy (c, name, sizeof c); + sc = rtems_task_create (rtems_build_name (c[0], c[1], c[2], c[3]), + threadGetOssPriorityValue (priority), + stackSize, + RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), + RTEMS_FLOATING_POINT|RTEMS_LOCAL, + &tid); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf ("threadCreate create failure for %s: %s\n",name, rtems_status_text (sc)); + return 0; + } + sc = rtems_semaphore_create (rtems_build_name (c[0], c[1], c[2], c[3]), + 1, + RTEMS_FIFO|RTEMS_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL, + 0, + &safe); + if (sc != RTEMS_SUCCESSFUL) { + rtems_task_delete (tid); + errlogPrintf("threadCreate create semaphore failure for %s: %s\n",name, rtems_status_text (sc)); + return 0; + } + + v = mallocMustSucceed (sizeof *v, "threadCreate_vars"); + v->name = mallocMustSucceed (strlen (name) + 1, "threadCreate_name"); + strcpy (v->name, name); + v->tid = tid; + v->taskSafeSemaphore = safe; + + rtems_semaphore_obtain (nameTableMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + avl_insert (nameTable, v); + rtems_semaphore_release (nameTableMutex); + + v->funptr = funptr; + v->parm = parm; + rtems_task_set_note (tid, TASK_VARIABLE_NOTE_INDEX, (rtems_unsigned32)v); + rtems_task_start (tid, threadWrapper, (rtems_task_argument)v); + return (threadId)tid; +} + +threadId +threadMustCreate (const char *name, + unsigned int priority, unsigned int stackSize, + THREADFUNC funptr,void *parm) +{ + threadId tid; + + if ((tid = threadCreate (name, priority, stackSize, funptr, parm)) == NULL) + cantProceed (0); + return tid; +} + +/* + * Destroy a thread + */ +void +threadDestroy (threadId id) +{ + rtems_id tid = (rtems_id)id; + rtems_unsigned32 nv; + struct taskVars *v; + int deleted = 0; + rtems_status_code sc; + + rtems_task_get_note (tid, TASK_VARIABLE_NOTE_INDEX, &nv); + v = (struct taskVars *)nv; + assert (tid == v->tid); + rtems_semaphore_obtain (v->taskSafeSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if ((tid != RTEMS_SELF) && (tid != (rtems_id)threadGetIdSelf())) { + /* FIXME: Should probably obtain the network semaphore here! */ + rtems_task_delete (tid); + deleted = 1; + } + rtems_semaphore_obtain (nameTableMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + avl_delete (nameTable, v); + rtems_semaphore_release (nameTableMutex); + rtems_semaphore_release (v->taskSafeSemaphore); + rtems_semaphore_delete (v->taskSafeSemaphore); + free (v->name); + free (v); + if (!deleted) + sc = rtems_task_delete (tid); +} + +void +threadSuspend (threadId id) +{ + rtems_id tid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_task_suspend (tid); + if(sc != RTEMS_SUCCESSFUL) + errlogPrintf("threadSuspend failed: %s\n", rtems_status_text (sc)); +} + +void threadResume(threadId id) +{ + rtems_id tid = (rtems_id)id; + rtems_status_code sc; + + sc = rtems_task_resume (tid); + if(sc != RTEMS_SUCCESSFUL) + errlogPrintf("threadResume failed: %s\n", rtems_status_text (sc)); +} + +int threadGetPriority(threadId id) +{ + rtems_id tid = (rtems_id)id; + rtems_status_code sc; + rtems_task_priority pri; + + sc = rtems_task_set_priority (tid, RTEMS_CURRENT_PRIORITY, &pri); + if (sc != RTEMS_SUCCESSFUL) + errlogPrintf("threadGetPriority failed: %s\n", rtems_status_text (sc)); + return threadGetOsiPriorityValue (pri); +} + +void +threadSetPriority (threadId id,int osip) +{ + rtems_id tid = (rtems_id)id; + rtems_status_code sc; + rtems_task_priority pri = threadGetOssPriorityValue(osip); + + sc = rtems_task_set_priority (tid, pri, &pri); + if (sc != RTEMS_SUCCESSFUL) + errlogPrintf("threadSetPriority failed\n", rtems_status_text (sc)); +} + +void +threadSetDestroySafe (void) +{ + rtems_unsigned32 nv; + struct taskVars *v; + + rtems_task_get_note (RTEMS_SELF, TASK_VARIABLE_NOTE_INDEX, &nv); + v = (struct taskVars *)nv; + rtems_semaphore_obtain (v->taskSafeSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); +} + +void +threadSetDestroyUnsafe (void) +{ + rtems_unsigned32 nv; + struct taskVars *v; + + rtems_task_get_note (RTEMS_SELF, TASK_VARIABLE_NOTE_INDEX, &nv); + v = (struct taskVars *)nv; + rtems_semaphore_release (v->taskSafeSemaphore); +} + +const char * +threadGetName (threadId id) +{ + rtems_id tid = (rtems_id)id; + rtems_unsigned32 nv; + struct taskVars *v; + + rtems_task_get_note (tid, TASK_VARIABLE_NOTE_INDEX, &nv); + v = (struct taskVars *)nv; + return (v->name); +} + +int +threadIsEqual (threadId id1, threadId id2) +{ + return (id1 == id2); +} + +int +threadIsSuspended (threadId id) +{ + rtems_id tid = (rtems_id)id; + rtems_status_code sc; + + switch (sc = rtems_task_is_suspended (tid)) { + case RTEMS_SUCCESSFUL: + return 0; + + case RTEMS_ALREADY_SUSPENDED: + return 1; + + default: + errlogPrintf("threadIsSuspended: %s\n", rtems_status_text (sc)); + return 0; + } +} + +int +threadIsReady (threadId id) +{ + return !threadIsSuspended(id); +} + +void +threadSleep (double seconds) +{ + rtems_status_code sc; + rtems_interval delay; + extern double rtemsTicksPerSecond_double; + + delay = seconds * rtemsTicksPerSecond_double; + sc = rtems_task_wake_after (delay); + if(sc != RTEMS_SUCCESSFUL) + errlogPrintf("threadSleep: %s\n", rtems_status_text (sc)); +} + +threadId +threadGetIdSelf (void) +{ + rtems_id tid; + + rtems_task_ident (RTEMS_SELF, 0, &tid); + return (threadId)tid; +} + +void +threadLockContextSwitch (void) +{ + rtems_mode oldMode; + + rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &oldMode); +} + +void +threadUnlockContextSwitch (void) +{ + rtems_mode oldMode; + + rtems_task_mode (RTEMS_PREEMPT, RTEMS_PREEMPT_MASK, &oldMode); +} + +threadId +threadNameToId (const char *name) +{ + return (threadId)tid_for_name (name); +} diff --git a/src/libCom/osi/os/default/osdAssert.c b/src/libCom/osi/os/default/osdAssert.c new file mode 100644 index 000000000..d5d0d69b4 --- /dev/null +++ b/src/libCom/osi/os/default/osdAssert.c @@ -0,0 +1,82 @@ +/* $Id$ + * assertUNIX.c + * Author: Jeffrey Hill + * Date: 02-27-95 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + */ + +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "dbDefs.h" +#include "epicsPrint.h" +#include "epicsVersion.h" +#include "epicsAssert.h" +#include "cantProceed.h" + +/* + * epicsAssert () + */ +epicsShareFunc void epicsShareAPI + epicsAssert (const char *pFile, const unsigned line, + const char *pExp, const char *pAuthorName) +{ + epicsPrintf ( +"\n\n\nA call to \"assert (%s)\" failed in %s line %d.\n", pExp, pFile, line); + + epicsPrintf ( +"The file \"core\" will be created in the current working directory.\n"); + + epicsPrintf ( +"Please save this file and the text of this message in order to assist\n"); + + epicsPrintf ( +"in diagnosing this problem.\n"); + + if (pAuthorName) { + + epicsPrintf ( +"Please send the text of this message to \"%s\"\n", pAuthorName); + + epicsPrintf ( +"(the author of this call to assert()) or to \"tech-talk@aps.anl.gov\"\n"); + + } + else { + + epicsPrintf ( +"Please contact the author of this software or else send the text of\n"); + + epicsPrintf ( +"this message to \"tech-talk@aps.anl.gov\"\n"); + + } + epicsPrintf ("This problem occurred in \"%s\"\n", epicsReleaseVersion); + + cantProceed ("assert fail"); +} + diff --git a/src/libCom/osi/os/default/osdFindGlobalSymbol.c b/src/libCom/osi/os/default/osdFindGlobalSymbol.c new file mode 100644 index 000000000..cfed70cb3 --- /dev/null +++ b/src/libCom/osi/os/default/osdFindGlobalSymbol.c @@ -0,0 +1,6 @@ +/* osi/osiFindGlobalSymbol.c */ + +#define epicsExportSharedSymbols +#include "osiFindGlobalSymbol.h" + +epicsShareFunc void * epicsShareAPI osiFindGlobalSymbol(const char *name) { return 0;} diff --git a/src/libCom/osi/os/default/osdFindGlobalSymbol.h b/src/libCom/osi/os/default/osdFindGlobalSymbol.h new file mode 100644 index 000000000..c1c5f1ecc --- /dev/null +++ b/src/libCom/osi/os/default/osdFindGlobalSymbol.h @@ -0,0 +1,5 @@ + +#ifdef osdFindGlobalSymbolh +#define osdFindGlobalSymbolh + +#endif /* osdFindGlobalSymbolh */ \ No newline at end of file diff --git a/src/libCom/osi/os/default/osdInterrupt.c b/src/libCom/osi/os/default/osdInterrupt.c new file mode 100644 index 000000000..31e798431 --- /dev/null +++ b/src/libCom/osi/os/default/osdInterrupt.c @@ -0,0 +1,47 @@ +/* osi/osiInterrupt.c */ + +/* Author: Marty Kraimer Date: 15JUL99 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +/* This is a version that does not allow osi calls at interrupt level */ + +#include +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "osiSem.h" +#include "cantProceed.h" +#include "errlog.h" +#include "osiInterrupt.h" + +static semId globalLock=0; +static int firstTime = 1; + +epicsShareFunc int epicsShareAPI interruptLock() +{ + if(firstTime) globalLock = semMutexMustCreate(); + semMutexMustTake(globalLock); + return(0); +} + +epicsShareFunc void epicsShareAPI interruptUnlock(int key) +{ + if(firstTime) cantProceed("interruptUnlock called before interruptLock\n"); + semMutexGive(globalLock); +} + +epicsShareFunc int epicsShareAPI interruptIsInterruptContext() { return(0);} + +epicsShareFunc void epicsShareAPI interruptContextMessage(const char *message) +{ + errlogPrintf("%s",message); +} + diff --git a/src/libCom/osi/os/default/osdInterrupt.h b/src/libCom/osi/os/default/osdInterrupt.h new file mode 100644 index 000000000..abe730776 --- /dev/null +++ b/src/libCom/osi/os/default/osdInterrupt.h @@ -0,0 +1,5 @@ + +#ifndef osdInterrupth +#define osdInterrupth + +#endif /* osdInterrupth */ \ No newline at end of file diff --git a/src/libCom/osi/os/default/osdPoolStatus.c b/src/libCom/osi/os/default/osdPoolStatus.c new file mode 100644 index 000000000..59e410fbc --- /dev/null +++ b/src/libCom/osi/os/default/osdPoolStatus.c @@ -0,0 +1,14 @@ + +#define epicsExportSharedSymbols +#include "osiPoolStatus.h" + +/* + * osiSufficentSpaceInPool () + * + * @@@@@ not implemented @@@@@ + * + */ +epicsShareFunc int epicsShareAPI osiSufficentSpaceInPool () +{ + return 1; +} diff --git a/src/libCom/osi/os/default/osdPoolStatus.h b/src/libCom/osi/os/default/osdPoolStatus.h new file mode 100644 index 000000000..1a72d1964 --- /dev/null +++ b/src/libCom/osi/os/default/osdPoolStatus.h @@ -0,0 +1,5 @@ + +#ifndef osdPoolStatush +#define osdPoolStatush + +#endif /* osdPoolStatush */ \ No newline at end of file diff --git a/src/libCom/osi/os/default/osdRing.c b/src/libCom/osi/os/default/osdRing.c new file mode 100644 index 000000000..4be21c0f9 --- /dev/null +++ b/src/libCom/osi/os/default/osdRing.c @@ -0,0 +1,190 @@ +/* $Id$ */ + +/* Author: Marty Kraimer Date: 15JUL99 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ +#include +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "dbDefs.h" +#include "cantProceed.h" +#include "osiInterrupt.h" +#include "osiRing.h" + + +typedef struct ringPvt { + int size; + int nextGet; + int nextPut; + int isFull; + char *buffer; +}ringPvt; + +epicsShareFunc ringId epicsShareAPI ringCreate(int size) +{ + ringPvt *pring = callocMustSucceed(1,sizeof(ringPvt),"ringCreate"); + pring->size = size; + pring->buffer = callocMustSucceed(size,sizeof(char),"ringCreate"); + return((void *)pring); +} + +epicsShareFunc void epicsShareAPI ringDelete(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + free((void *)pring->buffer); + free((void *)pring); +} + +epicsShareFunc int epicsShareAPI ringGet(ringId id, char *value,int nbytes) +{ + ringPvt *pring = (ringPvt *)id; + int nextGet = pring->nextGet; + int nextPut = pring->nextPut; + int size = pring->size; + int nToGet; + int lockKey; + + if(nextGet < nextPut) { + if(nbytes > (nextPut - nextGet)) return(0); + memcpy(value,&pring->buffer[nextGet],nbytes); + nextGet += nbytes; + if(nextGet>=size) nextGet = 0; + lockKey = interruptLock(); + pring->nextGet = nextGet; + pring->isFull = 0; + interruptUnlock(lockKey); + return(nbytes); + } + if(nextGet==nextPut && !pring->isFull ) return(0); + if(nbytes > (nextPut + (size - nextGet))) return(0); + nToGet = size - nextGet; + if(nToGet>nbytes) nToGet = nbytes; + memcpy(value,&pring->buffer[nextGet],nToGet); + value += nToGet; + nextGet += nToGet; + nToGet = nbytes - nToGet; + if(nToGet>0) { + nextGet = 0; + memcpy(value,&pring->buffer[0],nToGet); + nextGet += nToGet; + } + if(nextGet>=size) nextGet = 0; + lockKey = interruptLock(); + pring->nextGet = nextGet; + pring->isFull = 0; + interruptUnlock(lockKey); + return(nbytes); +} + +epicsShareFunc int epicsShareAPI ringPut(ringId id, char *value,int nbytes) +{ + ringPvt *pring = (ringPvt *)id; + int nextGet = pring->nextGet; + int nextPut = pring->nextPut; + int size = pring->size; + int nToPut; + int lockKey; + + if(nextPut < nextGet) { + if(nbytes > (nextGet - nextPut)) return(0); + memcpy(&pring->buffer[nextPut],value,nbytes); + nextPut += nbytes; + if(nextPut>=size) nextPut = 0; + lockKey = interruptLock(); + pring->nextPut = nextPut; + if(nextPut==nextGet) pring->isFull = 1; + interruptUnlock(lockKey); + return(nbytes); + } + if(nextGet==nextPut && pring->isFull ) return(0); + if(nbytes > (nextGet + (size - nextPut))) return(0); + nToPut = size - nextPut; + if(nToPut>nbytes) nToPut = nbytes; + memcpy(&pring->buffer[nextPut],value,nToPut); + value += nToPut; + nextPut += nToPut; + nToPut = nbytes - nToPut; + if(nToPut>0) { + nextPut = 0; + memcpy(&pring->buffer[0],value,nToPut); + nextPut += nToPut; + } + if(nextPut>=size) nextPut = 0; + lockKey = interruptLock(); + pring->nextPut = nextPut; + if(nextPut==nextGet) pring->isFull = 1; + interruptUnlock(lockKey); + return(nbytes); +} + +epicsShareFunc void epicsShareAPI ringFlush(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + int lockKey; + + lockKey = interruptLock(); + pring->nextGet = pring->nextPut = 0; + pring->isFull = 0; + interruptUnlock(lockKey); +} + +epicsShareFunc int epicsShareAPI ringFreeBytes(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + int n; + int lockKey; + + lockKey = interruptLock(); + n = pring->nextGet - pring->nextPut; + if(n<=0) n += pring->size; + if(pring->isFull) n = 0; + interruptUnlock(lockKey); + return(n); +} + +epicsShareFunc int epicsShareAPI ringUsedBytes(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + int n; + int lockKey; + + lockKey = interruptLock(); + n = pring->nextPut - pring->nextGet; + if(n<0) n += pring->size; + if(pring->isFull) n = pring->size; + interruptUnlock(lockKey); + return(n); +} + +epicsShareFunc int epicsShareAPI ringSize(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + return(pring->size); +} + +epicsShareFunc int epicsShareAPI ringIsEmpty(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + int lockKey; + int result; + + lockKey = interruptLock(); + result = (pring->nextGet==pring->nextPut && !pring->isFull) ? TRUE : FALSE; + interruptUnlock(lockKey); + return(result); +} + +epicsShareFunc int epicsShareAPI ringIsFull(ringId id) +{ + ringPvt *pring = (ringPvt *)id; + + return(pring->isFull); +} diff --git a/src/libCom/osi/os/default/osdRing.h b/src/libCom/osi/os/default/osdRing.h new file mode 100644 index 000000000..1b656071b --- /dev/null +++ b/src/libCom/osi/os/default/osdRing.h @@ -0,0 +1,5 @@ + +#ifndef osdRingh +#define osdRingh + +#endif /* osdRingh */ \ No newline at end of file diff --git a/src/libCom/osi/os/default/osdSigPipeIgnore.c b/src/libCom/osi/os/default/osdSigPipeIgnore.c new file mode 100644 index 000000000..691355db7 --- /dev/null +++ b/src/libCom/osi/os/default/osdSigPipeIgnore.c @@ -0,0 +1,11 @@ + +#define epicsExportSharedSymbols +#include "osiSigPipeIgnore.h" + +/* + * NOOP + */ +epicsShareFunc void epicsShareAPI installSigPipeIgnore (void) +{ +} + diff --git a/src/libCom/osi/os/default/osdSigPipeIgnore.h b/src/libCom/osi/os/default/osdSigPipeIgnore.h new file mode 100644 index 000000000..27370f0e3 --- /dev/null +++ b/src/libCom/osi/os/default/osdSigPipeIgnore.h @@ -0,0 +1,5 @@ + +#ifndef osdSigPipeIgnoreh +#define osdSigPipeIgnoreh + +#endif /* osdSigPipeIgnoreh */ \ No newline at end of file diff --git a/src/libCom/osi/os/posix/osdSem.c b/src/libCom/osi/os/posix/osdSem.c new file mode 100644 index 000000000..f2cea340b --- /dev/null +++ b/src/libCom/osi/os/posix/osdSem.c @@ -0,0 +1,237 @@ +/* osiSem.c */ + +/* Author: Marty Kraimer Date: 13AUG1999 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "osiSem.h" +#include "cantProceed.h" +#include "errlog.h" + + +typedef struct cond { + pthread_mutex_t mutex; + pthread_cond_t condition; +}cond; + + +typedef struct mutex { + pthread_mutexattr_t attr; + pthread_mutex_t lock; /*lock for structure */ + pthread_cond_t waitToBeOwner; + int count; + int owned; /* TRUE | FALSE */ + pthread_t ownerTid; +}mutex; + +semId semBinaryCreate(int initialState) +{ + cond *pcond; + int status; + + pcond = callocMustSucceed(1,sizeof(cond),"semBinaryCreate"); + status = pthread_mutex_init(&pcond->mutex,0); + if(status) { + errlogPrintf("pthread_mutex_init failed: error %s\n", + strerror(status)); + cantProceed("semBinaryCreate"); + } + status = pthread_cond_init(&pcond->condition,0); + if(status) { + errlogPrintf("pthread_cond_init failed: error %s\n", + strerror(status)); + cantProceed("semBinaryCreate"); + } + return((semId)pcond); +} + +void semBinaryDestroy(semId id) +{ + cond *pcond = (cond *)id; + int status; + + status = pthread_mutex_destroy(&pcond->mutex); + if(status) errlogPrintf("pthread_mutex_destroy error %s\n",strerror(status)); + status = pthread_cond_destroy(&pcond->condition); + if(status) errlogPrintf("pthread_cond_destroy error %s\n",strerror(status)); + free(pcond); +} + +void semBinaryGive(semId id) +{ + cond *pcond = (cond *)id; + int status; + + status = pthread_cond_signal(&pcond->condition); + if(status) errlogPrintf("pthread_cond_signal error %s\n",strerror(status)); +} + +semTakeStatus semBinaryTake(semId id) +{ + cond *pcond = (cond *)id; + int status; + + status = pthread_cond_wait(&pcond->condition,&pcond->mutex); + if(status) errlogPrintf("pthread_cond_wait error %s\n",strerror(status)); + if(status) return(semTakeError); + return(semTakeOK); +} + +semTakeStatus semBinaryTakeTimeout(semId id, double timeOut) +{ + cond *pcond = (cond *)id; + mutex *pmutex = (mutex *)id; + pthread_t tid = pthread_self(); + struct timespec wait; + int status; + + wait.tv_sec = timeOut; + wait.tv_nsec = (long)((timeOut - (double)wait.tv_sec) * 1e9); + status = pthread_cond_timedwait( + &pcond->condition,&pcond->mutex,&wait); + if(status==ETIMEDOUT) return(semTakeTimeout); + if(status) errlogPrintf("pthread_cond_wait error %s\n",strerror(status)); + return(0); +} + +semTakeStatus semBinaryTakeNoWait(semId id) +{ + return(semBinaryTakeTimeout(id,0.0)); +} + +void semBinaryShow(semId id) +{ +} + +semId semMutexCreate(void) { + mutex *pmutex; + int status; + + pmutex = callocMustSucceed(1,sizeof(mutex),"semMutexCreate"); + status = pthread_mutexattr_init(&pmutex->attr); + if(status) { + errlogPrintf("pthread_mutexattr_init failed: error %s\n", + strerror(status)); + cantProceed("semMutexCreate"); + } +#ifdef PTHREAD_PRIO_INHERIT + status = pthread_mutexattr_setprotocol(&pmutex->attr,PTHREAD_PRIO_INHERIT); + if(status) { + errlogPrintf("pthread_mutexattr_setprotocal failed: error %s\n", + strerror(status)); + } +#endif + status = pthread_mutex_init(&pmutex->lock,&pmutex->attr); + if(status) { + errlogPrintf("pthread_mutex_init failed: error %s\n", + strerror(status)); + cantProceed("semMutexCreate"); + } + status = pthread_cond_init(&pmutex->waitToBeOwner,0); + if(status) { + errlogPrintf("pthread_cond_init failed: error %s\n", + strerror(status)); + cantProceed("semMutexCreate"); + } + return((semId)pmutex); +} + +void semMutexDestroy(semId id) +{ + mutex *pmutex = (mutex *)id; + int status; + + status = pthread_mutex_destroy(&pmutex->lock); + if(status) errlogPrintf("pthread_mutex_destroy error %s\n",strerror(status)); + status = pthread_cond_destroy(&pmutex->waitToBeOwner); + if(status) errlogPrintf("pthread_cond_destroy error %s\n",strerror(status)); + status = pthread_mutexattr_destroy(&pmutex->attr); + if(status) errlogPrintf("pthread_mutexattr_destroy error %s\n",strerror(status)); + free(pmutex); +} + +void semMutexGive(semId id) +{ + mutex *pmutex = (mutex *)id; + pthread_mutex_lock(&pmutex->lock); + pmutex->count--; + if(pmutex->count == 0) { + pmutex->owned = 0; + pmutex->ownerTid = 0; + pthread_cond_signal(&pmutex->waitToBeOwner); + } + pthread_mutex_unlock(&pmutex->lock); +} +semTakeStatus semMutexTake(semId id) +{ + mutex *pmutex = (mutex *)id; + pthread_t tid = pthread_self(); + + pthread_mutex_lock(&pmutex->lock); + while(pmutex->owned && !pthread_equal(pmutex->ownerTid,tid)) + pthread_cond_wait(&pmutex->waitToBeOwner,&pmutex->lock); + pmutex->ownerTid = tid; + pmutex->owned = 1; + pmutex->count++; + pthread_mutex_unlock(&pmutex->lock); + return(0); +} +semTakeStatus semMutexTakeTimeout(semId id, double timeOut) +{ + mutex *pmutex = (mutex *)id; + pthread_t tid = pthread_self(); + struct timespec wait; + + wait.tv_sec = timeOut; + wait.tv_nsec = (long)((timeOut - (double)wait.tv_sec) * 1e9); + + pthread_mutex_lock(&pmutex->lock); + while(pmutex->owned && !pthread_equal(pmutex->ownerTid,tid)) { + int status; + status = pthread_cond_timedwait( + &pmutex->waitToBeOwner,&pmutex->lock,&wait); + if(!status) break; + if(status==ETIMEDOUT) return(semTakeTimeout); + return(semTakeError); + } + pmutex->ownerTid = tid; + pmutex->owned = 1; + pmutex->count++; + pthread_mutex_unlock(&pmutex->lock); + return(0); +} +semTakeStatus semMutexTakeNoWait(semId id) +{ + mutex *pmutex = (mutex *)id; + pthread_t tid = pthread_self(); + semTakeStatus status = semTakeError; + + pthread_mutex_lock(&pmutex->lock); + if(!pmutex->owned || pthread_equal(pmutex->ownerTid,tid)) { + pmutex->ownerTid = tid; + pmutex->owned = 1; + pmutex->count++; + status = 0; + } + pthread_mutex_unlock(&pmutex->lock); + return(status); +} +void semMutexShow(semId id) +{ + mutex *pmutex = (mutex *)id; + printf("ownerTid %p count %d owned %d\n", + pmutex->ownerTid,pmutex->count,pmutex->owned); +} diff --git a/src/libCom/osi/os/posix/osdSem.h b/src/libCom/osi/os/posix/osdSem.h new file mode 100644 index 000000000..dfed865ed --- /dev/null +++ b/src/libCom/osi/os/posix/osdSem.h @@ -0,0 +1 @@ +/* for a pure posix implementation no osdSem.h definitions are needed*/ diff --git a/src/libCom/osi/os/posix/osdSigPipeIgnore.c b/src/libCom/osi/os/posix/osdSigPipeIgnore.c new file mode 100644 index 000000000..6960a0d08 --- /dev/null +++ b/src/libCom/osi/os/posix/osdSigPipeIgnore.c @@ -0,0 +1,80 @@ + +/* + * install NOOP SIGPIPE handler + * + * escape into C to call signal because of a brain dead + * signal() func proto supplied in signal.h by gcc 2.7.2 + */ + +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "osiSigPipeIgnore.h" + +typedef void (*pSigFunc) (); + +static pSigFunc pReplacedFunc; + +static void localInstallSigPipeIgnore (void); + +/* + * ignoreSigPipe () + */ +static void ignoreSigPipe (int param) +{ + if (pReplacedFunc) { + (*pReplacedFunc) (param); + } + /* + * some versios of unix reset to SIG_DFL + * each time that the signal occurs + */ + localInstallSigPipeIgnore (); +} + +/* + * installSigPipeIgnore () + */ +epicsShareFunc void epicsShareAPI installSigPipeIgnore (void) +{ + static int init; + + if (init) { + return; + } + localInstallSigPipeIgnore(); + init = 1; +} + +/* + * localInstallSigPipeIgnore () + * + * dont allow disconnect to terminate process + * when running in UNIX environment + * + * allow error to be returned to sendto() + * instead of handling disconnect at interrupt + */ +static void localInstallSigPipeIgnore (void) +{ + pSigFunc sigRet; + + sigRet = signal (SIGPIPE, ignoreSigPipe); + if (sigRet==SIG_ERR) { + fprintf (stderr, "%s replace of SIGPIPE failed beacuse %s\n", + __FILE__, strerror(errno)); + } + else if (sigRet!=SIG_DFL && sigRet!=SIG_IGN) { + pReplacedFunc = sigRet; + } + /* + * no infinite loops + */ + if (pReplacedFunc==ignoreSigPipe) { + pReplacedFunc = NULL; + } +} + diff --git a/src/libCom/osi/os/posix/osdSigPipeIgnore.h b/src/libCom/osi/os/posix/osdSigPipeIgnore.h new file mode 100644 index 000000000..5828eeebb --- /dev/null +++ b/src/libCom/osi/os/posix/osdSigPipeIgnore.h @@ -0,0 +1,7 @@ + + +#ifndef osdSigPipeIgnoreh +#define osdSigPipeIgnoreh + + +#edndif /* osdSigPipeIgnoreh */ \ No newline at end of file diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c new file mode 100644 index 000000000..ee62f131e --- /dev/null +++ b/src/libCom/osi/os/posix/osdThread.c @@ -0,0 +1,225 @@ +/* osiThread.c */ + +/* Author: Marty Kraimer Date: 18JAN2000 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +/* This is a posix implementation of osiThread */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "osiThread.h" +#include "osiSem.h" +#include "cantProceed.h" +#include "errlog.h" + +static int firstTime = 1; +static pthread_key_t getpthreadInfo; + +typedef struct threadInfo { + pthread_t tid; + pthread_attr_t attr; + struct sched_param schedParam; + THREADFUNC createFunc; + void *createArg; + semId suspendSem; + int isSuspended; + int maxPriority; + int minPriority; + unsigned int osiPriority; + int schedPolicy; +} threadInfo; + +static void * start_routine(void *arg) +{ + threadInfo *pthreadInfo = (threadInfo *)arg; + pthread_setspecific(getpthreadInfo,arg); + (*pthreadInfo->createFunc)(pthreadInfo->createArg); + semBinaryDestroy(pthreadInfo->suspendSem); + pthread_attr_destroy(&pthreadInfo->attr); + free(pthreadInfo); + return(0); +} + +static int getOssPriorityValue(threadInfo *pthreadInfo) +{ + int maxPriority = pthreadInfo->maxPriority; + int minPriority = pthreadInfo->minPriority; + double slope,oss; + int ossInteger; + + if(maxPriority==minPriority) return(maxPriority); + slope = (double)(maxPriority - minPriority)/100.0; + oss = (double)pthreadInfo->osiPriority * slope; + if(minPrioritythreadStackBig) { + errlogPrintf("threadGetStackSize illegal argument (too large)"); + return stackSizeTable[threadStackBig]; + } + + return stackSizeTable[stackSizeClass]; +} + +threadId threadCreate(const char *name, + unsigned int priority, unsigned int stackSize, + THREADFUNC funptr,void *parm) +{ + threadInfo *pthreadInfo; + pthread_t *ptid; + int status; + + if(firstTime) { + firstTime = 0; + pthread_key_create(&getpthreadInfo,0); + } + pthreadInfo = callocMustSucceed(1,sizeof(threadInfo),"threadCreate"); + status = pthread_attr_init(&pthreadInfo->attr); + if(status) { + errlogPrintf("pthread_attr_init failed: error %s\n",strerror(status)); + cantProceed("threadCreate"); + } + status = pthread_attr_setdetachstate( + &pthreadInfo->attr, PTHREAD_CREATE_DETACHED); + if(status) { + errlogPrintf("pthread_attr_setdetachstate1 failed: error %s\n", + strerror(status)); + } + status = pthread_attr_setstacksize( + &pthreadInfo->attr, (size_t)stackSize); + if(status) { + errlogPrintf("pthread_attr_setstacksize failed: error %s\n", + strerror(status)); + } + /* DO WE WANT TO setscope ???? */ + /*pthread_attr_setscope(&pthreadInfo->attr,PTHREAD_SCOPE_SYSTEM);*/ + pthreadInfo->schedPolicy = SCHED_FIFO; + pthreadInfo->maxPriority = sched_get_priority_max(pthreadInfo->schedPolicy); + pthreadInfo->minPriority = sched_get_priority_min(pthreadInfo->schedPolicy); + pthreadInfo->osiPriority = priority; + status = pthread_attr_setschedpolicy( + &pthreadInfo->attr,pthreadInfo->schedPolicy); + if(status) { + errlogPrintf("pthread_attr_setschedpolicy failed: error %s\n", + strerror(status)); + cantProceed("threadCreate"); + } + pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo); + status = pthread_attr_setschedparam( + &pthreadInfo->attr,&pthreadInfo->schedParam); + if(status) { + errlogPrintf("pthread_attr_setschedparam failed: error %s\n", + strerror(status)); + cantProceed("threadCreate"); + } + pthreadInfo->suspendSem = semBinaryMustCreate(semFull); + status = pthread_create(&pthreadInfo->tid, + &pthreadInfo->attr,start_routine,pthreadInfo); + if(status) { + errlogPrintf("pthread_create failed: error %s\n",strerror(status)); + cantProceed("threadCreate"); + } + return((threadId)pthreadInfo); +} + +void threadSuspend() +{ + threadInfo *pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo); + pthreadInfo->isSuspended = 1; + semBinaryMustTake(pthreadInfo->suspendSem); +} + +void threadResume(threadId id) +{ + threadInfo *pthreadInfo = (threadInfo *)id; + pthreadInfo->isSuspended = 0; + semBinaryGive(pthreadInfo->suspendSem); +} + + +unsigned int threadGetPriority(threadId id) +{ + threadInfo *pthreadInfo = (threadInfo *)id; + return(pthreadInfo->osiPriority); +} + +void threadSetPriority(threadId id,unsigned int priority) +{ + threadInfo *pthreadInfo = (threadInfo *)id; + int status; + + pthreadInfo->osiPriority = priority; + pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo); + status = pthread_attr_setschedparam( + &pthreadInfo->attr,&pthreadInfo->schedParam); + if(status) { + errlogPrintf("threadSetPriority: pthread_attr_setschedparam failed %s\n", + strerror(status)); + } +} + +int threadIsEqual(threadId id1, threadId id2) +{ + threadInfo *p1 = (threadInfo *)id1; + threadInfo *p2 = (threadInfo *)id2; + return(pthread_equal(p1->tid,p2->tid)); +} + +int threadIsReady(threadId id) { + threadInfo *pthreadInfo = (threadInfo *)id; + return(pthreadInfo->isSuspended ? 1 : 0); +} + +int threadIsSuspended(threadId id) { + return(threadIsReady(id) ? 0 : 1); +} + +void threadSleep(double seconds) +{ + struct timespec delayTime; + struct timespec remainingTime; + + delayTime.tv_sec = (time_t)seconds; + delayTime.tv_nsec = (long)(seconds - (double)delayTime.tv_sec); + nanosleep(&delayTime,&remainingTime); +} + +threadId threadGetIdSelf(void) { + threadInfo *pthreadInfo = (threadInfo *)pthread_getspecific(getpthreadInfo); + return((threadId)pthreadInfo); +} diff --git a/src/libCom/osi/os/posix/osdThread.h b/src/libCom/osi/os/posix/osdThread.h new file mode 100644 index 000000000..706637239 --- /dev/null +++ b/src/libCom/osi/os/posix/osdThread.h @@ -0,0 +1,5 @@ + +#ifndef osdThreadh +#define osdThreadh + +#endif /* osdThreadh */ \ No newline at end of file diff --git a/src/libCom/osi/os/posix/osdTime.cpp b/src/libCom/osi/os/posix/osdTime.cpp new file mode 100644 index 000000000..b1c5b47f0 --- /dev/null +++ b/src/libCom/osi/os/posix/osdTime.cpp @@ -0,0 +1,51 @@ + +// +// should move the gettimeofday() proto +// into a different header +// +#include "osiSock.h" + +#define epicsExportSharedSymbols +#include "osiTime.h" + + +// +// osiTime::osdGetCurrent () +// +extern "C" epicsShareFunc int epicsShareAPI tsStampGetCurrent (TS_STAMP *pDest) +{ +# if defined(CLOCK_REALTIME) + struct timespec ts; + int status; + + status = clock_gettime (CLOCK_REALTIME, &ts); + if (status) { + return tsStampERROR; + } + *pDest = osiTime (ts); + return tsStampERROR; +# else + int status; + struct timeval tv; + + status = gettimeofday (&tv, NULL); + if (status) { + return tsStampERROR; + } + *pDest = osiTime (tv); + return tsStampERROR; +# endif +} + +// +// tsStampGetEvent () +// +extern "C" epicsShareFunc int epicsShareAPI tsStampGetEvent (TS_STAMP *pDest, unsigned eventNumber) +{ + if (eventNumber==tsStampEventCurrentTime) { + return tsStampGetCurrent (pDest); + } + else { + return tsStampERROR; + } +} \ No newline at end of file diff --git a/src/libCom/osi/os/posix/osdTime.h b/src/libCom/osi/os/posix/osdTime.h new file mode 100644 index 000000000..53685db6e --- /dev/null +++ b/src/libCom/osi/os/posix/osdTime.h @@ -0,0 +1,26 @@ + +/* + * $Id$ + * + * Author: Jeff Hill + */ + +#ifndef osdTimeh +#define osdTimeh + +#include + +/* + * "struct timespec" is not in all versions of POSIX 1. + * Solaris has it at ISO POSIX-1c so we will start from there, + * but may need to fine tune this + */ +#if _POSIX_VERSION < 199506L + struct timespec { + time_t tv_sec; /* seconds since some epoch */ + long tv_nsec; /* nanoseconds within the second */ + }; +#endif /* if _POSIX_VERSION < 199506L */ + +#endif /* ifndef osdTimeh */ +