22 #include <sys/types.h>
29 #include <epicsStdio.h>
30 #include <epicsMath.h>
31 #include <epicsThread.h>
32 #include <epicsMutex.h>
38 #define epicsExportSharedSymbols
43 extern int epicsThreadGetPosixPriority(epicsThreadOSD *pthreadInfo);
67 static ELLLIST threadRules = ELLLIST_INIT;
68 static epicsMutexId listLock;
69 static unsigned int cpuspecLen;
70 static char *sysConfigFile =
"/etc/rtrules";
71 static ENV_PARAM userHome = {
"HOME",
"/"};
72 static ENV_PARAM userConfigFile = {
"EPICS_MCORE_USERCONFIG",
".rtrules"};
82 static void parseModifiers(
threadRule *prule,
const char *policy,
const char *priority,
const char *cpus)
84 if (policy &&
'*' != policy[0] &&
'\0' != policy[0]) {
87 if (-1 == prule->policy) {
88 prule->ch_policy = prule->policy = 0;
91 if (priority &&
'*' != priority[0] &&
'\0' != priority[0]) {
92 prule->ch_priority = 1;
93 if (
'+' == priority[0] ||
'-' == priority[0]) {
94 prule->rel_priority = 1;
96 prule->priority = atoi(priority);
97 if (prule->priority > epicsThreadPriorityMax) prule->priority = epicsThreadPriorityMax;
98 if (prule->priority < epicsThreadPriorityMin) prule->priority = epicsThreadPriorityMin;
100 if (cpus &&
'*' != cpus[0] &&
'\0' != cpus[0]) {
101 prule->ch_affinity = 1;
109 long mcoreThreadRuleAdd(
const char *name,
const char *policy,
const char *priority,
const char *cpus,
const char *pattern)
115 errlogPrintf(
"Memory allocation error\n");
119 prule->name = strdup(name);
120 prule->pattern = strdup(pattern);
121 prule->cpus = strdup(cpus);
122 if (!prule->name || !prule->pattern || !prule->cpus) {
123 errlogPrintf(
"Memory allocation error\n");
127 parseModifiers(prule, policy, priority, cpus);
128 regcomp(&prule->reg, prule->pattern, (REG_EXTENDED || REG_NOSUB));
130 epicsMutexLock(listLock);
132 ellAdd(&threadRules, &prule->node);
133 epicsMutexUnlock(listLock);
144 epicsMutexLock(listLock);
145 prule = (
threadRule *) ellFirst(&threadRules);
147 if (0 == strcmp(name, prule->name)) {
148 ellDelete(&threadRules, &prule->node);
149 epicsMutexUnlock(listLock);
151 free(prule->pattern);
153 regfree(&prule->reg);
159 epicsMutexUnlock(listLock);
168 const int buflen = 128;
171 epicsMutexLock(listLock);
172 prule = (
threadRule *) ellFirst(&threadRules);
174 fprintf(epicsGetStdout(),
"No rules defined.\n");
175 epicsMutexUnlock(listLock);
178 fprintf(epicsGetStdout(),
" NAME PRIO POLICY %-*s PATTERN\n", cpuspecLen,
"AFFINITY");
181 fprintf(epicsGetStdout(),
"%16s ",
183 if (prule->ch_priority) {
184 if (prule->rel_priority) {
185 fprintf(epicsGetStdout(),
"%+4d ", prule->priority);
187 fprintf(epicsGetStdout(),
"%4d ", prule->priority);
190 fprintf(epicsGetStdout(),
" * ");
192 fprintf(epicsGetStdout(),
"%6s %-*s %s\n",
194 cpuspecLen, prule->ch_affinity?buf:
"*",
199 epicsMutexUnlock(listLock);
208 static void modifyRTProperties(epicsThreadId
id,
threadRule *prule)
211 unsigned int priority;
213 if (prule->ch_policy || prule->ch_priority) {
214 status = pthread_attr_getschedparam(&id->attr, &id->schedParam);
217 status = pthread_attr_getschedpolicy(&id->attr, &id->schedPolicy);
221 if (prule->ch_policy) {
222 id->schedPolicy = prule->policy;
223 status = pthread_attr_setschedpolicy(&id->attr, id->schedPolicy);
226 if (SCHED_FIFO == prule->policy || SCHED_RR == prule->policy) {
227 id->isRealTimeScheduled = 1;
229 id->isRealTimeScheduled = 0;
233 if (prule->ch_priority) {
234 if (prule->rel_priority) {
235 priority =
id->osiPriority + prule->priority;
236 if (priority > epicsThreadPriorityMax) priority = epicsThreadPriorityMax;
237 if (priority < epicsThreadPriorityMin) priority = epicsThreadPriorityMin;
239 priority = prule->priority;
241 id->osiPriority = priority;
242 id->schedParam.sched_priority = epicsThreadGetPosixPriority(
id);
243 status = pthread_attr_setschedparam(&id->attr, &id->schedParam);
248 status = pthread_setschedparam(id->tid, id->schedPolicy, &id->schedParam);
253 if (prule->ch_affinity) {
254 status = pthread_attr_setaffinity_np(&id->attr,
259 status = pthread_setaffinity_np(id->tid,
267 static void threadStartHook (epicsThreadId
id)
271 epicsMutexLock(listLock);
272 prule = (
threadRule *) ellFirst(&threadRules);
274 epicsMutexUnlock(listLock);
278 if (0 == regexec(&prule->reg, id->name, 0, NULL, 0)) {
279 modifyRTProperties(
id, prule);
283 epicsMutexUnlock(listLock);
289 void mcoreThreadModify(epicsThreadId
id,
const char *policy,
const char *priority,
const char *cpus)
294 parseModifiers(&rule, policy, priority, cpus);
295 modifyRTProperties(
id, &rule);
304 static int readRulesFromFile(
const char *file)
306 const int linelen = 256;
307 const char sep =
':';
309 unsigned int lineno = 0;
313 FILE *fp = fopen(file,
"r");
316 errlogPrintf(
"mcoreThreadRules: can't open rules file %s\n", file);
318 while (fgets(line, linelen, fp)) {
324 cp += strspn(cp,
" \t\r\n");
325 if (*cp ==
'#' || *cp ==
'\0')
327 for (i = 1; i < 5; i++) {
328 sp = strchr(cp, sep);
330 errlogPrintf(
"mcoreThreadRules: error parsing line %d of file %s\n", lineno, file);
336 if ((sp = strpbrk(cp,
"\n\r"))) {
347 static void once(
void *arg)
357 listLock = epicsMutexMustCreate();
359 envGetConfigParam(&userHome,
sizeof(userFile), userFile);
360 envGetConfigParam(&userConfigFile,
sizeof(userRel), userRel);
361 if (userFile[strlen(userFile)-1] !=
'/')
362 strcat(userFile,
"/");
363 strncat(userFile, userRel, len-strlen(userFile)-1);
365 count = readRulesFromFile(sysConfigFile);
366 printf(
"MCoreUtils: Read %d thread rule(s) from %s\n", count, sysConfigFile);
368 count = readRulesFromFile(userFile);
369 printf(
"MCoreUtils: Read %d thread rule(s) from %s\n", count, userFile);
371 epicsThreadHookAdd(threadStartHook);
379 static epicsThreadOnceId onceFlag = EPICS_THREAD_ONCE_INIT;
380 epicsThreadOnce(&onceFlag, once, NULL);