2060
2070
#endif /* End of #ifdef VXWORKS */
2072
#if (defined(RTEMS) || defined(bionic))
2064
2074
/* Note: the RTEMS API is UNIX-like except that it omits all SVR4
2065
2075
* features. RTEMS uses POSIX semaphores, and its shared-memory
2066
* mechanism is the same as the one we use for VxWorks. */
2076
* mechanism is the same as the one we use for VxWorks. The same
2077
* is true of Bionic. */
2068
2079
#include <sys/stat.h>
2069
2080
#include <sched.h>
2071
/* ---- Task Control services (RTEMS) ------------------------- */
2082
/* ---- Task Control services (POSIX) ------------------------- */
2073
#ifndef MAX_RTEMS_TASKS
2074
#define MAX_RTEMS_TASKS 50
2084
#ifndef MAX_POSIX_TASKS
2085
#define MAX_POSIX_TASKS 50
2079
int inUse; /* Boolean. */
2090
int inUse; /* Boolean. */
2080
2091
pthread_t threadId;
2092
void *value; /* Task variable value. */
2083
static int _rtemsTasks(int taskId, pthread_t *threadId)
2095
static void *_posixTasks(int *taskId, pthread_t *threadId, void **arg)
2085
static IonRtemsTask tasks[MAX_RTEMS_TASKS];
2086
static int initialized; /* Boolean. */
2097
static PosixTask tasks[MAX_POSIX_TASKS];
2098
static int initialized = 0;/* Boolean. */
2087
2099
static ResourceLock tasksLock;
2088
2100
pthread_t ownThreadId;
2093
/* NOTE: the taskId for an IonRtemsTask is 1 more than
2106
/* NOTE: the taskId for a PosixTask is 1 more than
2094
2107
* the index value for that task in the tasks table.
2095
* That is, taskIds range from 1 through MAX_RTEMS_TASKS
2108
* That is, taskIds range from 1 through MAX_POSIX_TASKS
2096
2109
* and -1 is an invalid task ID signifying "none". */
2098
2111
if (!initialized)
2100
2113
memset((char *) tasks, 0, sizeof tasks);
2101
2114
if (initResourceLock(&tasksLock) < 0)
2103
putErrmsg("Can't initialize RTEMS tasks table.", NULL);
2116
putErrmsg("Can't initialize POSIX tasks table.", NULL);
2107
2120
initialized = 1;
2110
2123
lockResource(&tasksLock);
2112
/* When taskId is 0, processing depends on the value
2125
/* taskId must never be NULL; it is always needed. */
2129
/* When *taskId is 0, processing depends on the value
2113
2130
* of threadID. If threadId is NULL, then the task ID
2114
* of the calling thread is returned (0 if the thread
2115
* doesn't have an assigned task ID). Otherwise, the
2116
* indicated thread is added as a new task and the ID
2117
* of that task is returned (-1 if the thread could not
2118
* be assigned a task ID).
2131
* of the calling thread (0 if the thread doesn't have
2132
* an assigned task ID) is written into *taskId.
2133
* Otherwise, the thread identified by *threadId is
2134
* added as a new task and the ID of that task (-1
2135
* if the thread could not be assigned a task ID) is
2136
* written into *taskId. In either case, NULL is
2120
* Otherwise, taskId must be in the range 1 through
2121
* MAX_RTEMS_TASKS inclusive and processing again
2139
* Otherwise, *taskId must be in the range 1 through
2140
* MAX_POSIX_TASKS inclusive and processing again
2122
2141
* depends on the value of threadId. If threadId is
2123
2142
* NULL then the indicated task ID is unassigned and
2124
2143
* is available for reassignment to another thread;
2125
* the return value is -1. Otherwise, the thread ID
2126
* for the indicated task is passed back in *threadId
2127
* and the task ID is returned. */
2144
* -1 is written into *taskId and NULL is returned.
2147
* The thread ID for the indicated task is
2148
* written into *threadId.
2150
* If arg is non-NULL, then the task variable
2151
* value for the indicated task is set to *arg.
2153
* The current value of the indicated task's
2154
* task variable is returned. */
2131
2158
if (threadId == NULL) /* Look up own task ID. */
2133
2160
ownThreadId = pthread_self();
2134
for (i = 0, task = tasks; i < MAX_RTEMS_TASKS;
2161
for (i = 0, task = tasks; i < MAX_POSIX_TASKS;
2137
2164
if (task->inUse == 0)
2142
2169
if (pthread_equal(task->threadId, ownThreadId))
2144
2172
unlockResource(&tasksLock);
2149
/* No task ID for this thread. */
2177
/* No task ID for this thread; sub-thread
2151
2180
unlockResource(&tasksLock);
2152
return 0; /* Sub-thread of a task. */
2155
2184
/* Assigning a task ID to this thread. */
2158
for (i = 0, task = tasks; i < MAX_RTEMS_TASKS; i++, task++)
2187
for (i = 0, task = tasks; i < MAX_POSIX_TASKS; i++, task++)
2160
2189
if (task->inUse == 0)
2179
2209
if (vacancy == -1)
2181
2211
putErrmsg("Can't start another task.", NULL);
2182
2213
unlockResource(&tasksLock);
2186
2217
task = tasks + vacancy;
2187
2218
task->inUse = 1;
2188
2219
task->threadId = *threadId;
2221
*taskId = vacancy + 1;
2189
2222
unlockResource(&tasksLock);
2193
2226
/* Operating on a previously assigned task ID. */
2195
CHKERR(taskId > 0 && taskId <= MAX_RTEMS_TASKS);
2196
task = tasks + (taskId - 1);
2228
CHKNULL((*taskId) > 0 && (*taskId) <= MAX_POSIX_TASKS);
2229
task = tasks + ((*taskId) - 1);
2197
2230
if (threadId == NULL) /* Unassigning this task ID. */
2199
2232
if (task->inUse)
2201
2234
task->inUse = 0;
2204
2238
unlockResource(&tasksLock);
2208
/* Just looking up the thread ID for this task ID. */
2242
/* Just looking up the thread ID for this task ID and/or
2243
* operating on task variable. */
2210
2245
if (task->inUse == 0) /* Invalid task ID. */
2212
2248
unlockResource(&tasksLock);
2216
2252
*threadId = task->threadId;
2258
value = task->value;
2217
2259
unlockResource(&tasksLock);
2221
2263
int sm_TaskIdSelf()
2223
int taskId = _rtemsTasks(0, NULL);
2224
2266
pthread_t threadId;
2268
oK(_posixTasks(&taskId, NULL, NULL));
2226
2269
if (taskId > 0)
2242
2285
* It needs to register itself as a task. */
2244
2287
threadId = pthread_self();
2245
return _rtemsTasks(0, &threadId);
2288
oK(_posixTasks(&taskId, &threadId, NULL));
2248
2292
int sm_TaskExists(int taskId)
2250
2294
pthread_t threadId;
2252
if (_rtemsTasks(taskId, &threadId) != taskId)
2296
oK(_posixTasks(&taskId, &threadId, NULL));
2254
2299
return 0; /* No such task. */
2268
2313
return 0; /* No such thread, or some other failure. */
2271
void sm_TaskVarAdd(int *var)
2316
void *sm_TaskVar(void **arg)
2273
oK(rtems_task_variable_add(rtems_task_self(), (void **) var, NULL));
2318
int taskId = sm_TaskIdSelf();
2321
return _posixTasks(&taskId, &threadId, arg);
2276
2324
void sm_TaskSuspend()
2310
static void *rtemsDriverThread(void *parm)
2359
static void posixTaskExit(int sig)
2364
void pthread_cancel(pthread_t threadId)
2366
/* NOTE that this is NOT a faithful implementation of
2367
* pthread_cancel(); there is no support for deferred
2368
* thread cancellation in Bionic (the Android subset
2369
* of Linux). It's just a code simplification, solely
2370
* for the express, limited purpose of shutting down a
2371
* task immediately, under the highly constrained
2372
* circumstances defined by sm_TaskSpawn, sm_TaskDelete,
2373
* and sm_Abort, below. */
2375
oK(pthread_kill(threadId, SIGUSR2));
2379
static void *posixDriverThread(void *parm)
2312
2381
SpawnParms parms;
2320
2389
memset((char *) parm, 0, sizeof(SpawnParms));
2392
/* Set up SIGUSR2 handler to enable shutdown. */
2394
struct sigaction actions;
2396
memset((char *) &actions, 0, sizeof actions);
2397
sigemptyset(&actions.sa_mask);
2398
actions.sa_flags = 0;
2399
actions.sa_handler = posixTaskExit;
2400
oK(sigaction(SIGUSR2, &actions, NULL));
2322
2402
/* Run main function of thread. */
2324
2404
parms.threadMainFunction(parms.arg1, parms.arg2, parms.arg3,
2383
2463
parms->arg9 = (int) arg9;
2384
2464
parms->arg10 = (int) arg10;
2385
2465
sm_ConfigurePthread(&attr, stackSize);
2386
errno = pthread_create(&threadId, &attr, rtemsDriverThread,
2466
errno = pthread_create(&threadId, &attr, posixDriverThread,
2387
2467
(void *) parms);
2394
taskId = _rtemsTasks(0, &threadId);
2474
taskId = 0; /* Requesting new task ID for thread. */
2475
oK(_posixTasks(&taskId, &threadId, NULL));
2395
2476
if (taskId < 0) /* Too many tasks running. */
2397
2478
if (pthread_kill(threadId, SIGTERM) == 0)
2408
2489
void sm_TaskForget(int taskId)
2410
oK(_rtemsTasks(taskId, NULL));
2491
oK(_posixTasks(&taskId, NULL, NULL));
2413
2494
void sm_TaskKill(int taskId, int sigNbr)
2415
2496
pthread_t threadId;
2417
if (_rtemsTasks(taskId, &threadId) != taskId)
2498
oK(_posixTasks(&taskId, &threadId, NULL));
2419
2501
return; /* No such task. */
2518
void sm_TaskVarAdd(int *var)
2601
void *sm_TaskVar(void **arg)
2520
return; /* All globals of Windows process are "task vars." */
2605
/* Each Windows process has its own distinct instance
2606
* of each global variable, so all global variables
2607
* are automatically "task variables". */
2611
/* Set value by dereferencing argument. */
2523
2619
void sm_TaskSuspend()
2744
void sm_TaskVarAdd(int *var)
2840
void *sm_TaskVar(void **arg)
2746
return; /* All globals of a UNIX process are "task vars." */
2844
/* Each UNIX process has its own distinct instance
2845
* of each global variable, so all global variables
2846
* are automatically "task variables". */
2850
/* Set value by dereferencing argument. */
2749
2858
void sm_TaskSuspend()
3026
3135
pid = sm_TaskSpawn(argv[0], argv[1], argv[2], argv[3],
3027
3136
argv[4], argv[5], argv[6], argv[7], argv[8],
3028
3137
argv[9], argv[10], 0, 0);
3029
#if defined (VXWORKS) || defined (RTEMS)
3138
#if defined (VXWORKS) || defined (RTEMS) || defined (bionic)
3032
3141
tagArgBuffers(0);