Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: fecbae4ada87c070a8dea549b9960fc888257b4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*******************************************************************************
 * Copyright (c) 2013 protos software gmbh (http://www.protos.de).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * CONTRIBUTORS:
 * 		Henrik Rentz-Reichert (initial contribution)
 *
 *******************************************************************************/

/**
 *
 * etThread.c POSIX implementation of etThread
 *
 */

#include "osal/etThread.h"

#include "debugging/etLogger.h"
#include "debugging/etMSCLogger.h"

#include <time.h>
#include <sys/unistd.h>
#include <errno.h>

typedef void *(*threadFunc)(void *);
void* etThread_execute(etThread* self);

void etThread_construct(
		etThread* self,
		etStacksize stacksize,
		etPriority priority,
		etThreadname threadName,
		etThreadFunction threadFunction,
		void* threadFunctionData)
{
	ET_MSC_LOGGER_SYNC_ENTRY("etThread", "construct")

	/* fill in data */
	self->stacksize = stacksize;
	self->priority = priority;
	self->threadName = threadName;
	self->threadFunction = threadFunction;
	self->threadFunctionData = threadFunctionData;
	self->started = ET_FALSE;

	ET_MSC_LOGGER_SYNC_EXIT
}

void etThread_start(etThread* self) {
	ET_MSC_LOGGER_SYNC_ENTRY("etThread", "start")
	{
		struct sched_param param;
		pthread_attr_t attr;

		const int policy = SCHED_RR;
		int minPriority = sched_get_priority_min(policy);
		int maxPriority = sched_get_priority_max(policy);

		if (self->priority<minPriority)
			self->priority = minPriority;
		if (self->priority>maxPriority)
			self->priority = maxPriority;

		param.sched_priority = self->priority;
		pthread_attr_init(&attr);
		pthread_attr_setschedparam(&attr, &param);
		pthread_attr_setschedpolicy(&attr, policy);
		pthread_attr_setstacksize(&attr, self->stacksize);

		pthread_create(&(self->osData), &attr, (threadFunc) etThread_execute, self);
		pthread_attr_destroy(&attr);
	}
	ET_MSC_LOGGER_SYNC_EXIT
}

void* etThread_execute(etThread* self){
	ET_MSC_LOGGER_SYNC_ENTRY("etThread", "execute")
	self->started = ET_TRUE;
	/* set cancel state, thread must not change to PTHREAD_CANCEL_DISABLE */
	pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, NULL);
	/* etThread_execute redirects the call from the thread to the execute function in the eTrice runtime to enable correct synchronous MSC logging */
	self->threadFunction(self->threadFunctionData);
	ET_MSC_LOGGER_SYNC_EXIT
	return NULL;
}

void etThread_destruct(etThread* self){
	ET_MSC_LOGGER_SYNC_ENTRY("etThread", "destruct")
	if (self->started) {
		self->started = ET_FALSE;
		/* Note: thread must not be in state PTHREAD_CANCEL_DISABLE */
		pthread_cancel(self->osData);
		pthread_join(self->osData, NULL);
	}
	ET_MSC_LOGGER_SYNC_EXIT
}

void etThread_sleep(etInt32 millis){
	ET_MSC_LOGGER_SYNC_ENTRY("etThread", "sleep")
	{
		struct timespec time;
		time.tv_sec = millis / 1000;
		time.tv_nsec = (millis - time.tv_sec * 1000) * 1000*1000;
		while(nanosleep(&time, &time) != 0) {
			if(errno != EINTR)
				break;
		}
	}
	ET_MSC_LOGGER_SYNC_EXIT
}

etOSThreadData etThread_self(void){
	return pthread_self();
}

etOSThreadId etThread_self_id(void){
	return pthread_self();
}

Back to the top