triton.c 16.0 KB
Newer Older
K
Kozlov Dmitry 已提交
1
#include <signal.h>
K
Kozlov Dmitry 已提交
2 3 4 5
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
D
Dmitry Kozlov 已提交
6
#include <unistd.h>
7
#include <limits.h>
8
#include <sys/resource.h>
K
Kozlov Dmitry 已提交
9

K
Kozlov Dmitry 已提交
10
#include "triton_p.h"
D
Dmitry Kozlov 已提交
11
#include "memdebug.h"
K
Kozlov Dmitry 已提交
12

13 14 15 16 17 18
#if __WORDSIZE == 32
#define WORKER_STACK_SIZE 64*1024
#else
#define WORKER_STACK_SIZE 128*1024
#endif

19
int thread_count = 2;
D
Dmitry Kozlov 已提交
20
int max_events = 64;
K
Kozlov Dmitry 已提交
21

D
Dmitry Kozlov 已提交
22
static spinlock_t threads_lock = SPINLOCK_INITIALIZER;
K
Kozlov Dmitry 已提交
23
static LIST_HEAD(threads);
K
Kozlov Dmitry 已提交
24
static LIST_HEAD(sleep_threads);
K
Kozlov Dmitry 已提交
25 26 27

static LIST_HEAD(ctx_queue);

D
Dmitry Kozlov 已提交
28
static spinlock_t ctx_list_lock = SPINLOCK_INITIALIZER;
K
Kozlov Dmitry 已提交
29 30
static LIST_HEAD(ctx_list);

31 32
static LIST_HEAD(init_list);

K
Kozlov Dmitry 已提交
33
static int terminate;
K
Kozlov Dmitry 已提交
34
static int need_terminate;
K
Kozlov Dmitry 已提交
35

36 37 38
static int need_config_reload;
static void (*config_reload_notify)(int);

K
Kozlov Dmitry 已提交
39
static mempool_t *ctx_pool;
40
static mempool_t *call_pool;
K
Kozlov Dmitry 已提交
41

42 43 44 45 46 47 48 49 50 51 52 53
struct triton_stat_t __export triton_stat;

static struct timeval ru_utime;
static struct timeval ru_stime;
static struct timespec ru_timestamp;
static int ru_refs;
static void ru_update(struct triton_timer_t *);
static struct triton_timer_t ru_timer = {
	.period = 1000,
	.expire = ru_update,
};
struct triton_context_t default_ctx;
D
Dmitry Kozlov 已提交
54

55 56
static struct triton_context_t __thread *this_ctx;

57 58
#define log_debug2(fmt, ...)

K
Kozlov Dmitry 已提交
59
void triton_thread_wakeup(struct _triton_thread_t *thread)
K
Kozlov Dmitry 已提交
60
{
61
	log_debug2("wake up thread %p\n", thread);
D
Dmitry Kozlov 已提交
62
	pthread_kill(thread->thread, SIGUSR1);
K
Kozlov Dmitry 已提交
63 64
}

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
static void __config_reload(void (*notify)(int))
{
	struct _triton_thread_t *t;
	int r;

	log_debug2("config_reload: enter\n");
	r = conf_reload(NULL);
	notify(r);

	spin_lock(&threads_lock);
	need_config_reload = 0;
	list_for_each_entry(t, &threads, entry)
		triton_thread_wakeup(t);
	spin_unlock(&threads_lock);
	log_debug2("config_reload: exit\n");
}

82
static void ctx_thread(struct _triton_context_t *ctx);
K
Kozlov Dmitry 已提交
83
static void* triton_thread(struct _triton_thread_t *thread)
K
Kozlov Dmitry 已提交
84
{
K
Kozlov Dmitry 已提交
85
	sigset_t set;
86
	int sig;
K
Kozlov Dmitry 已提交
87

88
	sigfillset(&set);
89 90 91
	sigdelset(&set, SIGKILL);
	sigdelset(&set, SIGSTOP);
	pthread_sigmask(SIG_BLOCK, &set, NULL);
92

93 94 95
	sigemptyset(&set);
	sigaddset(&set, SIGUSR1);
	sigaddset(&set, SIGQUIT);
K
Kozlov Dmitry 已提交
96

97 98 99
	pthread_mutex_lock(&thread->sleep_lock);
	pthread_mutex_unlock(&thread->sleep_lock);

100
	while (1) {
K
Kozlov Dmitry 已提交
101
		spin_lock(&threads_lock);
D
Dmitry Kozlov 已提交
102
		if (!list_empty(&ctx_queue) && !need_config_reload && triton_stat.thread_active <= thread_count) {
K
Kozlov Dmitry 已提交
103
			thread->ctx = list_entry(ctx_queue.next, typeof(*thread->ctx), entry2);
104
			log_debug2("thread: %p: dequeued ctx %p\n", thread, thread->ctx);
K
Kozlov Dmitry 已提交
105 106 107 108 109 110
			list_del(&thread->ctx->entry2);
			spin_unlock(&threads_lock);
			spin_lock(&thread->ctx->lock);
			thread->ctx->thread = thread;
			thread->ctx->queued = 0;
			spin_unlock(&thread->ctx->lock);
111
			__sync_sub_and_fetch(&triton_stat.context_pending, 1);
K
Kozlov Dmitry 已提交
112
		} else {
113 114 115 116 117 118 119
			if (triton_stat.thread_count > thread_count + triton_stat.context_sleeping) {
				__sync_sub_and_fetch(&triton_stat.thread_active, 1);
				__sync_sub_and_fetch(&triton_stat.thread_count, 1);
				list_del(&thread->entry);
				spin_unlock(&threads_lock);
				pthread_detach(pthread_self());
				log_debug2("thread: %p: exit\n", thread);
120
				_free(thread);
121 122
				return NULL;
			}
123
			log_debug2("thread: %p: sleeping\n", thread);
K
Kozlov Dmitry 已提交
124 125
			if (!terminate)
				list_add(&thread->entry2, &sleep_threads);
126
			
127
			if (__sync_sub_and_fetch(&triton_stat.thread_active, 1) == 0 && need_config_reload) {
128 129 130 131 132
				spin_unlock(&threads_lock);
				__config_reload(config_reload_notify);
			} else
				spin_unlock(&threads_lock);
			
133 134 135 136
			if (terminate) {
				spin_lock(&threads_lock);
				list_del(&thread->entry);
				spin_unlock(&threads_lock);
K
Kozlov Dmitry 已提交
137
				return NULL;
138
			}
K
Kozlov Dmitry 已提交
139 140 141 142

			//printf("thread %p: enter sigwait\n", thread);
			sigwait(&set, &sig);
			//printf("thread %p: exit sigwait\n", thread);
143

D
Dmitry Kozlov 已提交
144
			spin_lock(&threads_lock);
145
			__sync_add_and_fetch(&triton_stat.thread_active, 1);
D
Dmitry Kozlov 已提交
146
			if (!thread->ctx) {
147
				list_del(&thread->entry2);
D
Dmitry Kozlov 已提交
148
				spin_unlock(&threads_lock);
149
				continue;
D
Dmitry Kozlov 已提交
150 151
			}
			spin_unlock(&threads_lock);
K
Kozlov Dmitry 已提交
152
		}
K
Kozlov Dmitry 已提交
153 154

cont:
155
		log_debug2("thread %p: ctx=%p %p\n", thread, thread->ctx, thread->ctx ? thread->ctx->thread : NULL);
156
		this_ctx = thread->ctx->ud;
157 158
		if (thread->ctx->ud->before_switch)
			thread->ctx->ud->before_switch(thread->ctx->ud, thread->ctx->bf_arg);
159

160
		log_debug2("thread %p: switch to %p\n", thread, thread->ctx);
161
		ctx_thread(thread->ctx);
162
		log_debug2("thread %p: switch from %p %p\n", thread, thread->ctx, thread->ctx->thread);
163

164 165
		spin_lock(&thread->ctx->lock);
		if (thread->ctx->pending) {
166
			spin_unlock(&thread->ctx->lock);
167 168 169 170
			goto cont;
		}
		thread->ctx->thread = NULL;
		spin_unlock(&thread->ctx->lock);
171

172 173
		if (thread->ctx->need_free) {
			log_debug2("- context %p removed\n", thread->ctx);
174
			thread->ctx->ud->tpd = NULL;
175
			mempool_free(thread->ctx);
176 177
		}

178
		thread->ctx = NULL;
K
Kozlov Dmitry 已提交
179 180 181
	}
}

182 183 184 185
static void ctx_thread(struct _triton_context_t *ctx)
{
	struct _triton_md_handler_t *h;
	struct _triton_timer_t *t;
186
	struct _triton_ctx_call_t *call;
187 188
	uint64_t tt;

189 190 191 192 193 194 195
	log_debug2("ctx %p %p: enter\n", ctx, ctx->thread);
	if (ctx->need_close) {
		if (ctx->ud->close)
			ctx->ud->close(ctx->ud);
		ctx->need_close = 0;
	}

196
	while (1) {
197 198 199 200 201 202 203 204
		spin_lock(&ctx->lock);
		if (!list_empty(&ctx->pending_timers)) {
			t = list_entry(ctx->pending_timers.next, typeof(*t), entry2);
			list_del(&t->entry2);
			t->pending = 0;
			spin_unlock(&ctx->lock);
			__sync_sub_and_fetch(&triton_stat.timer_pending, 1);
			read(t->fd, &tt, sizeof(tt));
D
bugfix  
Dmitry Kozlov 已提交
205 206
			if (t->ud)
				t->ud->expire(t->ud);
207
			continue;
208
		}
209 210 211 212
		if (!list_empty(&ctx->pending_handlers)) {
			h = list_entry(ctx->pending_handlers.next, typeof(*h), entry2);
			list_del(&h->entry2);
			h->pending = 0;
213
			spin_unlock(&ctx->lock);
214 215 216 217 218 219 220 221 222 223 224
			__sync_sub_and_fetch(&triton_stat.md_handler_pending, 1);
			if (h->trig_epoll_events & (EPOLLIN | EPOLLERR | EPOLLHUP))
				if (h->ud && h->ud->read)
					if (h->ud->read(h->ud))
						continue;
			if (h->trig_epoll_events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
				if (h->ud && h->ud->write)
					if (h->ud->write(h->ud))
						continue;
			h->trig_epoll_events = 0;
			continue;
225
		}
226 227 228 229 230 231 232
		if (!list_empty(&ctx->pending_calls)) {
			call = list_entry(ctx->pending_calls.next, typeof(*call), entry);
			list_del(&call->entry);
			spin_unlock(&ctx->lock);
			call->func(call->arg);
			mempool_free(call);
			continue;
233
		}
234 235 236
		ctx->pending = 0;
		spin_unlock(&ctx->lock);
		break;	
237
	}
238 239

	log_debug2("ctx %p %p: exit\n", ctx, ctx->thread);
240 241
}

K
Kozlov Dmitry 已提交
242
struct _triton_thread_t *create_thread()
K
Kozlov Dmitry 已提交
243
{
244
	pthread_attr_t attr;
245
	struct _triton_thread_t *thread = _malloc(sizeof(*thread));
246 247
	if (!thread) {
		triton_log_error("out of memory");
D
Dmitry Kozlov 已提交
248
		return NULL;
249
	}
D
Dmitry Kozlov 已提交
250

251
	pthread_attr_init(&attr);
252
	pthread_attr_setstacksize(&attr, WORKER_STACK_SIZE);
253

D
Dmitry Kozlov 已提交
254
	memset(thread, 0, sizeof(*thread));
255 256 257
	pthread_mutex_init(&thread->sleep_lock, NULL);
	pthread_cond_init(&thread->sleep_cond, NULL);
	pthread_mutex_lock(&thread->sleep_lock);
258
	if (pthread_create(&thread->thread, &attr, (void*(*)(void*))triton_thread, thread)) {
D
Dmitry Kozlov 已提交
259 260 261
		triton_log_error("pthread_create: %s", strerror(errno));
		return NULL;
	}
K
Kozlov Dmitry 已提交
262

263 264
	__sync_add_and_fetch(&triton_stat.thread_count, 1);
	__sync_add_and_fetch(&triton_stat.thread_active, 1);
D
Dmitry Kozlov 已提交
265

K
Kozlov Dmitry 已提交
266 267 268
	return thread;
}

269
int triton_queue_ctx(struct _triton_context_t *ctx)
K
Kozlov Dmitry 已提交
270
{
271
	ctx->pending = 1;
272
	if (ctx->thread || ctx->queued || ctx->init)
K
Kozlov Dmitry 已提交
273
		return 0;
K
Kozlov Dmitry 已提交
274

K
Kozlov Dmitry 已提交
275
	spin_lock(&threads_lock);
D
Dmitry Kozlov 已提交
276
	if (list_empty(&sleep_threads) || need_config_reload || triton_stat.thread_active > thread_count) {
277 278 279 280
		if (ctx->priority)
			list_add(&ctx->entry2, &ctx_queue);
		else
			list_add_tail(&ctx->entry2, &ctx_queue);
K
Kozlov Dmitry 已提交
281
		spin_unlock(&threads_lock);
D
Dmitry Kozlov 已提交
282
		ctx->queued = 1;
283
		log_debug2("ctx %p: queued\n", ctx);
284
		__sync_add_and_fetch(&triton_stat.context_pending, 1);
K
Kozlov Dmitry 已提交
285
		return 0;
K
Kozlov Dmitry 已提交
286
	}
K
Kozlov Dmitry 已提交
287

D
Dmitry Kozlov 已提交
288
	ctx->thread = list_entry(sleep_threads.next, typeof(*ctx->thread), entry2);
K
Kozlov Dmitry 已提交
289
	ctx->thread->ctx = ctx;
290
	log_debug2("ctx %p: assigned to thread %p\n", ctx, ctx->thread);
K
Kozlov Dmitry 已提交
291
	list_del(&ctx->thread->entry2);
K
Kozlov Dmitry 已提交
292 293 294
	spin_unlock(&threads_lock);

	return 1;
K
Kozlov Dmitry 已提交
295 296
}

297
int __export triton_context_register(struct triton_context_t *ud, void *bf_arg)
K
Kozlov Dmitry 已提交
298
{
299
	struct _triton_context_t *ctx = mempool_alloc(ctx_pool);
K
Kozlov Dmitry 已提交
300

301
	log_debug2("ctx %p: register\n", ctx);
302 303 304
	if (!ctx)
		return -1;

K
Kozlov Dmitry 已提交
305 306
	memset(ctx, 0, sizeof(*ctx));
	ctx->ud = ud;
307
	ctx->bf_arg = bf_arg;
308
	ctx->init = 1;
K
Kozlov Dmitry 已提交
309
	spinlock_init(&ctx->lock);
K
Kozlov Dmitry 已提交
310 311 312 313
	INIT_LIST_HEAD(&ctx->handlers);
	INIT_LIST_HEAD(&ctx->timers);
	INIT_LIST_HEAD(&ctx->pending_handlers);
	INIT_LIST_HEAD(&ctx->pending_timers);
314
	INIT_LIST_HEAD(&ctx->pending_calls);
315

K
Kozlov Dmitry 已提交
316 317
	ud->tpd = ctx;

K
Kozlov Dmitry 已提交
318
	spin_lock(&ctx_list_lock);
D
Dmitry Kozlov 已提交
319
	list_add_tail(&ctx->entry, &ctx_list);
K
Kozlov Dmitry 已提交
320
	spin_unlock(&ctx_list_lock);
321

322 323
	__sync_add_and_fetch(&triton_stat.context_sleeping, 1);
	__sync_add_and_fetch(&triton_stat.context_count, 1);
D
Dmitry Kozlov 已提交
324

325
	return 0;
K
Kozlov Dmitry 已提交
326 327
}

328
void __export triton_context_unregister(struct triton_context_t *ud)
K
Kozlov Dmitry 已提交
329
{
330
	struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
D
Dmitry Kozlov 已提交
331
	struct _triton_ctx_call_t *call;
K
Kozlov Dmitry 已提交
332
	struct _triton_thread_t *t;
D
Dmitry Kozlov 已提交
333

334
	log_debug2("ctx %p: unregister\n", ctx);
335

D
Dmitry Kozlov 已提交
336 337 338 339 340
	while (!list_empty(&ctx->pending_calls)) {
		call = list_entry(ctx->pending_calls.next, typeof(*call), entry);
		list_del(&call->entry);
		mempool_free(call);
	}
K
Kozlov Dmitry 已提交
341 342 343

	if (!list_empty(&ctx->handlers)) {
		triton_log_error("BUG:ctx:triton_unregister_ctx: handlers is not empty");
K
Kozlov Dmitry 已提交
344 345 346 347 348 349
		{
			struct _triton_md_handler_t *h;
			list_for_each_entry(h, &ctx->handlers, entry)
				if (h->ud)
					printf("%p\n", h->ud);
		}
K
Kozlov Dmitry 已提交
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
		abort();
	}
	if (!list_empty(&ctx->pending_handlers)) {
		triton_log_error("BUG:ctx:triton_unregister_ctx: pending_handlers is not empty");
		abort();
	}
	if (!list_empty(&ctx->timers)) {
		triton_log_error("BUG:ctx:triton_unregister_ctx: timers is not empty");
		abort();
	}
	if (!list_empty(&ctx->pending_timers)) {
		triton_log_error("BUG:ctx:triton_unregister_ctx: pending_timers is not empty");
		abort();
	}

D
Dmitry Kozlov 已提交
365
	ctx->need_free = 1;
K
Kozlov Dmitry 已提交
366
	spin_lock(&ctx_list_lock);
K
Kozlov Dmitry 已提交
367
	list_del(&ctx->entry);
368 369 370 371
	if (__sync_sub_and_fetch(&triton_stat.context_count, 1) == 1) {
		if (need_terminate)
			terminate = 1;
	}
K
Kozlov Dmitry 已提交
372
	spin_unlock(&ctx_list_lock);
D
Dmitry Kozlov 已提交
373
	
K
Kozlov Dmitry 已提交
374 375 376 377
	if (terminate) {
		list_for_each_entry(t, &threads, entry)
			triton_thread_wakeup(t);
	}
K
Kozlov Dmitry 已提交
378
}
379

380 381 382 383 384 385 386
void __export triton_context_set_priority(struct triton_context_t *ud, int prio)
{
	struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
	
	ctx->priority = prio > 0;
}

387
void __export triton_context_schedule()
388
{
389
	struct _triton_context_t *ctx = (struct _triton_context_t *)this_ctx->tpd;
390 391
	struct _triton_thread_t *t = NULL;
	
392
	log_debug2("ctx %p: enter schedule\n", ctx);
393
	__sync_add_and_fetch(&triton_stat.context_sleeping, 1);
394
	__sync_sub_and_fetch(&triton_stat.thread_active, 1);
395
	pthread_mutex_lock(&ctx->thread->sleep_lock);
396 397 398 399 400 401 402 403 404 405
	while (1) {
		if (ctx->wakeup) {
			ctx->wakeup = 0;
			break;
		} else {
			if (!t && triton_stat.thread_count <= thread_count + triton_stat.context_sleeping) {
				t = create_thread();
				spin_lock(&threads_lock);
				list_add_tail(&t->entry, &threads);
				spin_unlock(&threads_lock);
406
				pthread_mutex_unlock(&t->sleep_lock);
407
			}
408
			pthread_cond_wait(&ctx->thread->sleep_cond, &ctx->thread->sleep_lock);
409 410
		}
	}
411
	pthread_mutex_unlock(&ctx->thread->sleep_lock);
412
	__sync_sub_and_fetch(&triton_stat.context_sleeping, 1);
413
	__sync_add_and_fetch(&triton_stat.thread_active, 1);
414
	log_debug2("ctx %p: exit schedule\n", ctx);
415 416
}

417 418 419 420 421
struct triton_context_t __export *triton_context_self(void)
{
	return this_ctx;
}

422 423 424 425 426 427 428 429
void triton_context_print(void)
{
	struct _triton_context_t *ctx;

	list_for_each_entry(ctx, &ctx_list, entry)
		printf("%p\n", ctx);
}

430
void __export triton_context_wakeup(struct triton_context_t *ud)
431 432
{
	struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
433
	int r = 0;
434

435 436
	log_debug2("ctx %p: wakeup\n", ctx);

437 438 439 440 441 442
	if (ctx->init) {
		__sync_sub_and_fetch(&triton_stat.context_sleeping, 1);
		spin_lock(&ctx->lock);
		ctx->init = 0;
		if (ctx->pending)
			r = triton_queue_ctx(ctx);
443
		spin_unlock(&ctx->lock);
444 445 446
		if (r)
			triton_thread_wakeup(ctx->thread);
		return;
447
	}
448

449
	pthread_mutex_lock(&ctx->thread->sleep_lock);
450
	ctx->wakeup = 1;
451 452
	pthread_cond_signal(&ctx->thread->sleep_cond);
	pthread_mutex_unlock(&ctx->thread->sleep_lock);
453
}
K
Kozlov Dmitry 已提交
454

455 456 457 458
int __export triton_context_call(struct triton_context_t *ud, void (*func)(void *), void *arg)
{
	struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
	struct _triton_ctx_call_t *call = mempool_alloc(call_pool);
459
	int r;
460 461 462 463 464 465 466 467 468

	if (!call)
		return -1;
	
	call->func = func;
	call->arg = arg;

	spin_lock(&ctx->lock);
	list_add_tail(&call->entry, &ctx->pending_calls);
469
	r = triton_queue_ctx(ctx);
470 471
	spin_unlock(&ctx->lock);

472 473 474
	if (r)
		triton_thread_wakeup(ctx->thread);

475 476 477
	return 0;
}

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
void __export triton_cancel_call(struct triton_context_t *ud, void (*func)(void *))
{
	struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
	struct list_head *pos, *n;
	struct _triton_ctx_call_t *call;

	list_for_each_safe(pos, n, &ctx->pending_calls) {
		call = list_entry(pos, typeof(*call), entry);
		if (call->func != func)
			continue;
		list_del(&call->entry);
		mempool_free(call);
	}
}

493 494 495 496 497 498 499 500 501 502
void __export triton_collect_cpu_usage(void)
{
	struct rusage rusage;

	if (__sync_fetch_and_add(&ru_refs, 1) == 0) {
		triton_timer_add(NULL, &ru_timer, 0);
		getrusage(RUSAGE_SELF, &rusage);
		clock_gettime(CLOCK_MONOTONIC, &ru_timestamp);
		ru_utime = rusage.ru_utime;
		ru_stime = rusage.ru_stime;
K
Kozlov Dmitry 已提交
503
		triton_stat.cpu = 0;
504 505 506 507 508 509 510 511 512 513 514 515 516 517
	}
}

void __export triton_stop_collect_cpu_usage(void)
{
	if (__sync_sub_and_fetch(&ru_refs, 1) == 0)
		triton_timer_del(&ru_timer);
}

static void ru_update(struct triton_timer_t *t)
{
	struct timespec ts;
	struct rusage rusage;
	unsigned int dt;
K
Kozlov Dmitry 已提交
518
	unsigned int val;
519 520 521 522 523

	getrusage(RUSAGE_SELF, &rusage);
	clock_gettime(CLOCK_MONOTONIC, &ts);

	dt = (ts.tv_sec - ru_timestamp.tv_sec) * 1000000 + (ts.tv_nsec - ru_timestamp.tv_nsec) / 1000000;
K
Kozlov Dmitry 已提交
524 525 526
	val = (double)((rusage.ru_utime.tv_sec - ru_utime.tv_sec) * 1000000 + (rusage.ru_utime.tv_usec - ru_utime.tv_usec) + 
	      (rusage.ru_stime.tv_sec - ru_stime.tv_sec) * 1000000 + (rusage.ru_stime.tv_usec - ru_stime.tv_usec)) / dt * 100;

K
Kozlov Dmitry 已提交
527
	triton_stat.cpu = val;
528 529 530 531 532 533

	ru_timestamp = ts;
	ru_utime = rusage.ru_utime;
	ru_stime = rusage.ru_stime;
}

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
void __export triton_register_init(int order, void (*func)(void))
{
	struct _triton_init_t *i1, *i = _malloc(sizeof(*i));
	struct list_head *p = init_list.prev;


	i->order = order;
	i->func = func;

	while (p != &init_list) {
		i1 = list_entry(p, typeof(*i1), entry);
		if (order > i1->order)
			break;
		p = p->prev;
	}
	list_add(&i->entry, p);
}

D
Dmitry Kozlov 已提交
552
int __export triton_init(const char *conf_file)
K
Kozlov Dmitry 已提交
553
{
D
Dmitry Kozlov 已提交
554
	ctx_pool = mempool_create(sizeof(struct _triton_context_t));
555
	call_pool = mempool_create(sizeof(struct _triton_ctx_call_t));
K
Kozlov Dmitry 已提交
556

K
Kozlov Dmitry 已提交
557 558 559 560 561 562
	if (conf_load(conf_file))
		return -1;

	if (log_init())
		return -1;

K
Kozlov Dmitry 已提交
563 564
	if (md_init())
		return -1;
K
Kozlov Dmitry 已提交
565

K
Kozlov Dmitry 已提交
566 567
	if (timer_init())
		return -1;
K
Kozlov Dmitry 已提交
568

569 570 571
	if (event_init())
		return -1;

K
Kozlov Dmitry 已提交
572 573
	triton_context_register(&default_ctx, NULL);

D
Dmitry Kozlov 已提交
574 575 576 577 578
	return 0;
}

int __export triton_load_modules(const char *mod_sect)
{
579 580
	struct _triton_init_t *i;

K
Kozlov Dmitry 已提交
581 582
	if (load_modules(mod_sect))
		return -1;
583 584 585 586 587 588 589

	while (!list_empty(&init_list)) {
		i = list_entry(init_list.next, typeof(*i), entry);
		i->func();
		list_del(&i->entry);
		_free(i);
	}
D
Dmitry Kozlov 已提交
590
	
K
Kozlov Dmitry 已提交
591
	return 0;
K
Kozlov Dmitry 已提交
592 593
}

594 595 596 597 598 599 600 601 602 603 604 605
void __export triton_conf_reload(void (*notify)(int))
{
	spin_lock(&threads_lock);
	need_config_reload = 1;
	config_reload_notify = notify;
	if (triton_stat.thread_active == 0) {
		spin_unlock(&threads_lock);
		__config_reload(notify);
	} else
		spin_unlock(&threads_lock);
}

K
Kozlov Dmitry 已提交
606
void __export triton_run()
K
Kozlov Dmitry 已提交
607
{
K
Kozlov Dmitry 已提交
608
	struct _triton_thread_t *t;
K
Kozlov Dmitry 已提交
609
	int i;
610
	char *opt;
K
Kozlov Dmitry 已提交
611
	struct timespec ts;
612 613 614 615

	opt = conf_get_opt("core", "thread-count");
	if (opt && atoi(opt) > 0)
		thread_count = atoi(opt);
K
Kozlov Dmitry 已提交
616

D
Dmitry Kozlov 已提交
617 618 619 620 621 622
	for(i = 0; i < thread_count; i++) {
		t = create_thread();
		if (!t)
			_exit(-1);

		list_add_tail(&t->entry, &threads);
623
		pthread_mutex_unlock(&t->sleep_lock);
K
Kozlov Dmitry 已提交
624
	}
K
Kozlov Dmitry 已提交
625

K
Kozlov Dmitry 已提交
626 627
	clock_gettime(CLOCK_MONOTONIC, &ts);
	triton_stat.start_time = ts.tv_sec;
D
Dmitry Kozlov 已提交
628

K
Kozlov Dmitry 已提交
629 630
	md_run();
	timer_run();
631 632

	triton_context_wakeup(&default_ctx);
K
Kozlov Dmitry 已提交
633 634
}

K
Kozlov Dmitry 已提交
635
void __export triton_terminate()
K
Kozlov Dmitry 已提交
636
{
637
	struct _triton_context_t *ctx;
K
Kozlov Dmitry 已提交
638 639 640 641
	int r;

	need_terminate = 1;

K
Kozlov Dmitry 已提交
642
	spin_lock(&ctx_list_lock);
D
Dmitry Kozlov 已提交
643
	list_for_each_entry(ctx, &ctx_list, entry) {
K
Kozlov Dmitry 已提交
644
		spin_lock(&ctx->lock);
D
Dmitry Kozlov 已提交
645
		ctx->need_close = 1;
K
Kozlov Dmitry 已提交
646 647 648
		r = triton_queue_ctx(ctx);
		if (r)
			triton_thread_wakeup(ctx->thread);
K
Kozlov Dmitry 已提交
649
		spin_unlock(&ctx->lock);
K
Kozlov Dmitry 已提交
650
	}
K
Kozlov Dmitry 已提交
651
	spin_unlock(&ctx_list_lock);
K
Kozlov Dmitry 已提交
652

653 654 655 656 657 658 659 660 661
	while (1) {
		spin_lock(&threads_lock);
		if (list_empty(&threads)) {
			spin_unlock(&threads_lock);
			break;
		}
		spin_unlock(&threads_lock);
		sleep(1);
	}
K
Kozlov Dmitry 已提交
662 663 664
	
	md_terminate();
	timer_terminate();
K
Kozlov Dmitry 已提交
665 666
}