summaryrefslogtreecommitdiff
path: root/runtime/src/runtime.c
blob: 94724382b97ce11fb68d711f5aa4832bb66b1b38 (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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/* \brief MARSIO运行时环境管理器
 *
 * 运行时环境管理器提供重要的基础设施服务,包括:
 * (1)全局共享内存映射及管理;
 * (2)应用及应用数据面线程管理。
 * 
 *  \author Qiuwen Lu<[email protected]>
 *  \date 2016-10-19
 */

#include <assert.h>
#include <stdio.h>
#include <mr_common.h>
#include <mr_runtime.h>
#include <rte_malloc.h>

#include <runtime.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/signalfd.h>
#include <stdlib.h>
#include <unistd.h>

void mr_runtime_init()
{
	int ret = mr_global_ctx_init();
	MR_CHECK(ret >= 0, "RuntimeInit, Initialize global ctx failed(ret = %d). ", ret);
	ret = mr_global_cfg_init();
	MR_CHECK(ret >= 0, "RuntimeInit, Initialize global config failed(ret = %d). ", ret);
	
	struct mr_global_ctx * g_ctx = mr_global_ctx_get();
	assert(g_ctx != NULL);

	struct mr_runtime_ctx * rt_ctx;
	rt_ctx = rte_zmalloc("RuntimeCtx", sizeof(struct mr_runtime_ctx), 0);
	MR_CHECK(rt_ctx != NULL, "RuntimeInit, Cannot alloc memory for runtime ctx.");

	rt_ctx->app_ctx = app_manager_create();
	MR_CHECK(rt_ctx->app_ctx != NULL, "RuntimeInit, App manager initialize failed. ");

	rt_ctx->hwinfo_ctx = hwinfo_manager_create();
	MR_CHECK(rt_ctx->hwinfo_ctx != NULL, "RuntimeInit, HwInfo manager initialize failed. ");

	rt_ctx->id_ctx = id_manager_create();
	MR_CHECK(rt_ctx->id_ctx != NULL, "RuntimeInit, ID Manager initialize failed. ");

	rt_ctx->ev_ctx = app_ev_manager_create(rt_ctx);
	MR_CHECK(rt_ctx->ev_ctx != NULL, "RuntimeInit, App event initialize failed. ");
	
	pthread_t pid_crash_monitor;
	pthread_create(&pid_crash_monitor, NULL, app_thread_crash_monitor, (void *)rt_ctx->ev_ctx);

	app_crash_cb_register(rt_ctx->ev_ctx, app_mamager_crash_event_handler, rt_ctx->app_ctx);
	
	g_ctx->ctx_runtime = rt_ctx;
	return;
}

void mr_runtime_slave_init()
{
	int ret = mr_global_ctx_slave_init();
	MR_CHECK(ret >= 0, "RuntimeSlaveInit, Initialize global ctx failed(ret = %d). ", ret);
	
	ret = mr_global_cfg_slave_init();
	MR_CHECK(ret >= 0, "RuntimeSlaveInit, Initialize global config failed(ret = %d). ", ret);

	struct mr_global_ctx * g_ctx = mr_global_ctx_get();
	assert(g_ctx != NULL);
	
	struct mr_runtime_ctx * rt_ctx = (struct mr_runtime_ctx *)g_ctx->ctx_runtime;
	assert(g_ctx->ctx_runtime != NULL);
	assert(rt_ctx->app_ctx != NULL);
	assert(rt_ctx->hwinfo_ctx != NULL);
	assert(rt_ctx->app_ctx != NULL);
	return;
}

// 是否自动退出:处理信号和exit函数
static int autoexit = 0;

struct exit_handler
{
	void(* fn)(void * arg);
	void * arg;
};

// 退出处理函数
struct exit_handler exit_handlers[MR_RUNTIME_MAX_NR_EXIT_HANDLER];
unsigned int nr_exit_handlers;

// 当前运行线程信息
pthread_mutex_t thread_ids_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t thread_ids[MR_SID_MAX];
unsigned int nr_thread_ids;

// 信号屏蔽信息
sigset_t __autoexit_sigmask;


/* 处理运行时异常退出的情况。该模块保证应用触发异常,收到退出信号时,
 * 调用退出处理函数,释放资源,保证内存的一致性。*/

#if 0
static void __autoexit_raise(int status __rte_unused, void * arg __rte_unused)
{
	void * rtvalue;

	pthread_mutex_lock(&thread_ids_lock);

	// 通知其他线程退出
	for (int i = 0; i < nr_thread_ids; i++)
	{
		if (pthread_kill(thread_ids[i], 0) < 0) continue;
		pthread_cancel(thread_ids[i]);
	}

	
	// 等待其他线程退出
	for (int i = 0; i < nr_thread_ids; i++)
	{
		if (pthread_kill(thread_ids[i], 0) < 0) continue;
		pthread_join(thread_ids[i], &rtvalue);
	}

	pthread_mutex_unlock(&thread_ids_lock);
	
	// 运行注册的退出处理函数
	for (int i = 0; i < nr_exit_handlers; i++)
		exit_handlers[i].fn(arg);

	// 应用信息注销
	mr_app_manager_appinfo_unregister();
	return;
}

#endif

#if 0
static void __autoexit_thread_setup()
{
	// 记录线程ID
	pthread_mutex_lock(&thread_ids_lock);
	pthread_t pid = pthread_self();
	thread_ids[nr_thread_ids++] = pid;
	pthread_mutex_unlock(&thread_ids_lock);
	
	// 设置线程信号屏蔽,不处理SIGINT、SIGSEGV等信号
	sigset_t oldset;
	pthread_sigmask(SIG_BLOCK, &__autoexit_sigmask, &oldset);
}

// 信号处理线程
void * __autoexit_thread(void * arg)
{
	pthread_t self_pid = pthread_self();
	pthread_detach(self_pid);

	int sfd;
	ssize_t s;
	struct signalfd_siginfo fdsi;

	sfd = signalfd(-1, &__autoexit_sigmask, 0);
	assert(sfd != 0);

	while(1)
	{
		s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
		if(s != sizeof(struct signalfd_siginfo))
		{
			continue;
		}
		
		switch(fdsi.ssi_signo)
		{
		case SIGINT:
		case SIGSEGV:
		case SIGTERM:
		default:
			exit(EXIT_SUCCESS);
		}
	}
}

 static void __autoexit_signal_handler(int signo)
{
	 switch (signo)
	 {
	 case SIGINT:
	 case SIGSEGV:
	 case SIGTERM:
	 default:
		 __autoexit_raise(1, NULL);
		 _Exit(EXIT_SUCCESS);
	 }
}

#endif

#if 0
static void __autoexit_setup()
{
	sigemptyset(&__autoexit_sigmask);
	sigaddset(&__autoexit_sigmask, SIGINT);
	sigaddset(&__autoexit_sigmask, SIGTERM);
	sigprocmask(SIG_BLOCK, &__autoexit_sigmask, NULL);

#if MR_RUNTIME_SIGHANDLE_BY_SIGFD
	pthread_t pid;
	pthread_create(&pid, NULL, __autoexit_thread, NULL);
#else
	struct sigaction act, oact;
	act.sa_handler = __autoexit_signal_handler;
	act.sa_mask = __autoexit_sigmask;
	act.sa_flags = 0;

	int ret = sigaction(SIGINT, &act, &oact);
	assert(ret >= 0);
	ret = sigaction(SIGTERM, &act, &oact);
	assert(ret >= 0);
#endif

	autoexit = 1;
}

#endif

int mr_app_register(const char * appsym, cpu_mask_t cpumask, 
	unsigned int autoexit __rte_unused)
{
	//if (autoexit) __autoexit_setup();
	mr_runtime_slave_init();
	mr_app_manager_appinfo_register(appsym, cpumask);
	//on_exit(__autoexit_raise, NULL);
	return 0;
}

int mr_thread_register()
{
	//if (autoexit) __autoexit_thread_setup();
	mr_app_manager_thread_register();
	return 0;
}

void mr_thread_on_exit_register(void(*exit_fn)(void * arg), void * arg)
{
	return;
}

void mr_thread_hook()
{
	if(autoexit) pthread_testcancel();
}

void mr_on_exit_register(void(*exit_fn)(void * arg), void * arg)
{
	exit_handlers[nr_exit_handlers].fn = exit_fn;
	exit_handlers[nr_exit_handlers].arg = arg;
	nr_exit_handlers++;
	return;
}