summaryrefslogtreecommitdiffstats
path: root/Master/Real-Time Systems/Praktikum1/Aufgabe1/src/main.cpp
blob: 65eef37e606daac25cb656956f4be944b4bc9736 (plain)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * main.cpp
 *
 *  Created on: 31.10.2010
 *      Author: sven
 */
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// debug printing
#ifdef DEBUG_MODE
#include <stdio.h>
	#define DEBUG_PRINT(format, args...)\
			{\
				static char message[512];\
				snprintf(message,512,format, ##args);\
				fprintf(stdout, "[%s: %d] : %s\n", __PRETTY_FUNCTION__,__LINE__, message);\
				fflush(stdout);\
			}
#else
	#define DEBUG_PRINT(format, args...)
#endif // DEBUG_MODE

/*
 * global variables
 */
sem_t main_block,timer_block;
pthread_t timer_thread;
bool stop_timer_thread = false;
pthread_mutex_t stop_mutex = PTHREAD_MUTEX_INITIALIZER;
// 0 sec
const long TIMER_INTERVAL_SECS = 0;
// 10 msec
const long TIMER_INTERVAL_USECS = 10000;

struct sigaction timer_action, quit_action;
/*
 * function prototypes
 */
void readSensors();
void initializeClock();
void initializeMain();
void WaitForNextCycle();
void ActuateProcess();
bool CalculateNewSetValues();
void Error();
void* TimerThreadProc(void*);
void timer_handler(int);

void* TimerThreadProc(void*) {
	/**
	 * Timer code originally from
	 * http://www.informit.com/articles/article.aspx?p=23618&seqNum=14
	 */
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	bool stop_me = false;
	struct itimerval timer;
	/* Install timer_handler as the signal handler for SIGALRM. */
	timer_action.sa_handler = timer_handler;
	sigemptyset(&timer_action.sa_mask);
	timer_action.sa_flags = 0;
	sigaction(SIGALRM,&timer_action,NULL);

	/* Configure the timer to expire after
	 * TIMER_INTERVAL_SECS + TIMER_INTERVAL_USECS... */
	timer.it_value.tv_sec = TIMER_INTERVAL_SECS;
	timer.it_value.tv_usec = TIMER_INTERVAL_USECS;
	/* ... and every TIMER_INTERVAL_SECS+TIMER_INTERVAL_USECS after that. */
	timer.it_interval.tv_sec = TIMER_INTERVAL_SECS;
	timer.it_interval.tv_usec = TIMER_INTERVAL_USECS;
	/* If the timer code is ITIMER_REAL,
	 * the process is sent a SIGALRM signal after the
	 * specified wall-clock time has elapsed*/
	setitimer (ITIMER_REAL, &timer, NULL);
	while(1) {
		pthread_mutex_lock(&stop_mutex);
		stop_me = stop_timer_thread;
		pthread_mutex_unlock(&stop_mutex);
		if(stop_me) {
			DEBUG_PRINT("exiting thread Process: %d Thread: %lu",(int)getpid(),pthread_self());
			pthread_exit(NULL);
		}
		DEBUG_PRINT("waiting for timer_handler Process: %d Thread: %lu",(int)getpid(),pthread_self());
		sem_wait(&timer_block);
		DEBUG_PRINT("waking up main Process: %d Thread: %lu",(int)getpid(),pthread_self());
		sem_post(&main_block);
	}
	DEBUG_PRINT("should never happen Process: %d Thread: %lu",(int)getpid(),pthread_self());
	return NULL;
}

void timer_handler(int signum) {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	static int count = 0;
	DEBUG_PRINT("timer expired %d times", ++count);
	sem_post(&timer_block);
	DEBUG_PRINT("exit");
}

void quit_handler(int signum) {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	int semval;
	pthread_mutex_lock(&stop_mutex);
	stop_timer_thread = true;
	pthread_mutex_unlock(&stop_mutex);
	sem_getvalue(&timer_block,&semval);
	if(semval > 0) {
		DEBUG_PRINT("waking up timer thread");
		sem_post(&timer_block);
	}
	pthread_join(timer_thread,NULL);
	DEBUG_PRINT("Joined timer thread");
	//clean up
	sem_destroy(&timer_block);
	sem_destroy(&main_block);
	pthread_mutex_destroy(&stop_mutex);
	DEBUG_PRINT("exit");
	exit(EXIT_SUCCESS);
}

void WaitForNextCycle() {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	sem_wait(&main_block);
	DEBUG_PRINT("exit");
}

void readSensors() {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	struct timeval tv;
	struct timezone tz;
	struct tm *tm;
	gettimeofday(&tv, &tz);
	tm=localtime(&tv.tv_sec);
	printf(" %d:%02d:%02d %lu \n", tm->tm_hour, tm->tm_min,
	    tm->tm_sec, tv.tv_usec);
	DEBUG_PRINT("exit");
}
void Error() {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	DEBUG_PRINT("exit");
}
bool CalculateNewSetValues() {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	DEBUG_PRINT("exit");
	return true;
}
void ActuateProcess() {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	DEBUG_PRINT("exit");
}
void initializeClock()
{
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());
	pthread_create(&timer_thread,NULL,TimerThreadProc,NULL);
	DEBUG_PRINT("exit");
}

void initializeMain() {
	DEBUG_PRINT("entry Process: %d Thread: %lu",(int)getpid(),pthread_self());

	/* init semaphore as closed */
	sem_init(&main_block,0,0);
	sem_init(&timer_block,0,0);

    /* catch all interesting signals */
	quit_action.sa_handler = quit_handler;
	sigemptyset(&quit_action.sa_mask);
	quit_action.sa_flags = 0;
	sigaction(SIGTERM,&quit_action,NULL);
	sigaction(SIGQUIT,&quit_action,NULL);
	sigaction(SIGINT,&quit_action,NULL);
	sigaction(SIGHUP,&quit_action,NULL);
    DEBUG_PRINT("exit");
}

int main(int argc, char* argv[])
{
	initializeMain();
	initializeClock();
	while(1) {
		readSensors();
		if(CalculateNewSetValues())
			ActuateProcess();
		else
			Error();
		WaitForNextCycle();
	}
	return EXIT_SUCCESS;
}