renamed files
This commit is contained in:
87
src/libCom/osi/os/RTEMS/osdInterrupt.c
Normal file
87
src/libCom/osi/os/RTEMS/osdInterrupt.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* RTEMS osiInterrupt.c
|
||||
* $Id$
|
||||
* Author: W. Eric Norum
|
||||
* eric@cls.usask.ca
|
||||
* (306) 966-6055
|
||||
*/
|
||||
|
||||
#include <syslog.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
11
src/libCom/osi/os/RTEMS/osdInterrupt.h
Normal file
11
src/libCom/osi/os/RTEMS/osdInterrupt.h
Normal file
@@ -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);
|
||||
191
src/libCom/osi/os/RTEMS/osdSem.c
Normal file
191
src/libCom/osi/os/RTEMS/osdSem.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* RTEMS osiSem.c
|
||||
* $Id$
|
||||
* Author: W. Eric Norum
|
||||
* eric@cls.usask.ca
|
||||
* (306) 966-6055
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
407
src/libCom/osi/os/RTEMS/osdThread.c
Normal file
407
src/libCom/osi/os/RTEMS/osdThread.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* RTEMS osiThread.c
|
||||
* $Id$
|
||||
* Author: W. Eric Norum
|
||||
* eric@cls.usask.ca
|
||||
* (306) 966-6055
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <avl.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
82
src/libCom/osi/os/default/osdAssert.c
Normal file
82
src/libCom/osi/os/default/osdAssert.c
Normal file
@@ -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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
|
||||
6
src/libCom/osi/os/default/osdFindGlobalSymbol.c
Normal file
6
src/libCom/osi/os/default/osdFindGlobalSymbol.c
Normal file
@@ -0,0 +1,6 @@
|
||||
/* osi/osiFindGlobalSymbol.c */
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "osiFindGlobalSymbol.h"
|
||||
|
||||
epicsShareFunc void * epicsShareAPI osiFindGlobalSymbol(const char *name) { return 0;}
|
||||
5
src/libCom/osi/os/default/osdFindGlobalSymbol.h
Normal file
5
src/libCom/osi/os/default/osdFindGlobalSymbol.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifdef osdFindGlobalSymbolh
|
||||
#define osdFindGlobalSymbolh
|
||||
|
||||
#endif /* osdFindGlobalSymbolh */
|
||||
47
src/libCom/osi/os/default/osdInterrupt.c
Normal file
47
src/libCom/osi/os/default/osdInterrupt.c
Normal file
@@ -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 <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
5
src/libCom/osi/os/default/osdInterrupt.h
Normal file
5
src/libCom/osi/os/default/osdInterrupt.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifndef osdInterrupth
|
||||
#define osdInterrupth
|
||||
|
||||
#endif /* osdInterrupth */
|
||||
14
src/libCom/osi/os/default/osdPoolStatus.c
Normal file
14
src/libCom/osi/os/default/osdPoolStatus.c
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "osiPoolStatus.h"
|
||||
|
||||
/*
|
||||
* osiSufficentSpaceInPool ()
|
||||
*
|
||||
* @@@@@ not implemented @@@@@
|
||||
*
|
||||
*/
|
||||
epicsShareFunc int epicsShareAPI osiSufficentSpaceInPool ()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
5
src/libCom/osi/os/default/osdPoolStatus.h
Normal file
5
src/libCom/osi/os/default/osdPoolStatus.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifndef osdPoolStatush
|
||||
#define osdPoolStatush
|
||||
|
||||
#endif /* osdPoolStatush */
|
||||
190
src/libCom/osi/os/default/osdRing.c
Normal file
190
src/libCom/osi/os/default/osdRing.c
Normal file
@@ -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 <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
5
src/libCom/osi/os/default/osdRing.h
Normal file
5
src/libCom/osi/os/default/osdRing.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifndef osdRingh
|
||||
#define osdRingh
|
||||
|
||||
#endif /* osdRingh */
|
||||
11
src/libCom/osi/os/default/osdSigPipeIgnore.c
Normal file
11
src/libCom/osi/os/default/osdSigPipeIgnore.c
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "osiSigPipeIgnore.h"
|
||||
|
||||
/*
|
||||
* NOOP
|
||||
*/
|
||||
epicsShareFunc void epicsShareAPI installSigPipeIgnore (void)
|
||||
{
|
||||
}
|
||||
|
||||
5
src/libCom/osi/os/default/osdSigPipeIgnore.h
Normal file
5
src/libCom/osi/os/default/osdSigPipeIgnore.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifndef osdSigPipeIgnoreh
|
||||
#define osdSigPipeIgnoreh
|
||||
|
||||
#endif /* osdSigPipeIgnoreh */
|
||||
237
src/libCom/osi/os/posix/osdSem.c
Normal file
237
src/libCom/osi/os/posix/osdSem.c
Normal file
@@ -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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
1
src/libCom/osi/os/posix/osdSem.h
Normal file
1
src/libCom/osi/os/posix/osdSem.h
Normal file
@@ -0,0 +1 @@
|
||||
/* for a pure posix implementation no osdSem.h definitions are needed*/
|
||||
80
src/libCom/osi/os/posix/osdSigPipeIgnore.c
Normal file
80
src/libCom/osi/os/posix/osdSigPipeIgnore.c
Normal file
@@ -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 <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
7
src/libCom/osi/os/posix/osdSigPipeIgnore.h
Normal file
7
src/libCom/osi/os/posix/osdSigPipeIgnore.h
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
#ifndef osdSigPipeIgnoreh
|
||||
#define osdSigPipeIgnoreh
|
||||
|
||||
|
||||
#edndif /* osdSigPipeIgnoreh */
|
||||
225
src/libCom/osi/os/posix/osdThread.c
Normal file
225
src/libCom/osi/os/posix/osdThread.c
Normal file
@@ -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 <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#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(minPriority<maxPriority) oss = minPriority +(double)(oss + .5);
|
||||
else oss = maxPriority - (oss - .5);
|
||||
return(oss);
|
||||
}
|
||||
|
||||
|
||||
#if CPU_FAMILY == MC680X0
|
||||
#define ARCH_STACK_FACTOR 1
|
||||
#elif CPU_FAMILY == SPARC
|
||||
#define ARCH_STACK_FACTOR 2
|
||||
#else
|
||||
#define ARCH_STACK_FACTOR 2
|
||||
#endif
|
||||
/*
|
||||
* threadGetStackSize ()
|
||||
*/
|
||||
unsigned int threadGetStackSize (threadStackSizeClass stackSizeClass)
|
||||
{
|
||||
static const unsigned stackSizeTable[threadStackBig+1] =
|
||||
{4000*ARCH_STACK_FACTOR, 6000*ARCH_STACK_FACTOR, 11000*ARCH_STACK_FACTOR};
|
||||
|
||||
if (stackSizeClass<threadStackSmall) {
|
||||
errlogPrintf("threadGetStackSize illegal argument (too small)");
|
||||
return stackSizeTable[threadStackBig];
|
||||
}
|
||||
|
||||
if (stackSizeClass>threadStackBig) {
|
||||
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);
|
||||
}
|
||||
5
src/libCom/osi/os/posix/osdThread.h
Normal file
5
src/libCom/osi/os/posix/osdThread.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifndef osdThreadh
|
||||
#define osdThreadh
|
||||
|
||||
#endif /* osdThreadh */
|
||||
51
src/libCom/osi/os/posix/osdTime.cpp
Normal file
51
src/libCom/osi/os/posix/osdTime.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
26
src/libCom/osi/os/posix/osdTime.h
Normal file
26
src/libCom/osi/os/posix/osdTime.h
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*/
|
||||
|
||||
#ifndef osdTimeh
|
||||
#define osdTimeh
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* "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 */
|
||||
|
||||
Reference in New Issue
Block a user