1 #ifdef NEWEV
2 
3 /* ----------------------------------------------------------------------------
4  * Please see 4 Jul. 2015 meeting slides for conceptual explanation.
5  * 'Subtree' has special meaning and its 'ID' is very important concept for
6  * understanding this code.
7  *
8  * Please contact Donghwi Kim for further questions,
9  * via e-mail: [email protected]
10  */
11 #include "debug.h"
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <tree.h>
16 #include <key_value_store.h>
17 #include "scalable_event.h"
18 
19 #include "mtcp.h"
20 #include "mos_api.h"
21 #include "mtcp_api.h"
22 
23 #define NEWHASH
24 #ifdef NEWHASH
25 #include "mtcp_util.h"
26 #define XXHSEED 18446744073709551557ULL
27 #endif
28 /*----------------------------------------------------------------------------*/
29 #define POWER_OF_TWO(x) (!((x - 1) & (x)))
30 
31 #define MAX_EVENTS  30240
32 #define KVS_BUCKETS 1024
33 #define KVS_ENTRIES 102400
34 #define MAX_DEPTH   MAX_EVENTS
35 #define NEWID(id, ev, cb) (id ^ hash64(ev, cb))
36 #define IS_UDE(e) ((e)->ev >= (1 << NUM_BEV))
37 #define IS_FLOATING_EVENT(e) (!(e)->ft && IS_UDE(e))
38 
39 struct _tree_node_t *g_evroot;
40 event_t g_evid;
41 
42 static __thread stree_t *g_cur_stree = NULL;
43 static __thread tree_node_t *g_cur_ev = NULL;
44 
45 static __thread struct {
46 	struct _tree_node_t *stack[MAX_EVENTS];
47 	struct _tree_node_t **sp;
48 } g_evstack;
49 
50 #define free(x) do {				\
51 		assert(x);			\
52 		free(x);			\
53 	} while (0)
54 
55 /*----------------------------------------------------------------------------*/
56 struct devent {
57 	event_t ev;            /* event id = key */
58 	tree_node_t *ptr;      /* ptr to the event node in the d-forest = value */
59 	struct devent *next;   /* next pointer */
60 };
61 #define MAX_BUCKET 2048
62 #define HASHVAL(x) ((x) & (MAX_BUCKET-1))
63 struct devent* g_dfTable[MAX_BUCKET] = {0};  /* d-forest hash table */
64 /*----------------------------------------------------------------------------*/
65 /* simple hash table implementation */
66 static bool
67 dforest_store(event_t ev, tree_node_t* ptr)
68 {
69 	struct devent *de, *p;
70 	int idx;
71 
72 	if ((de = malloc(sizeof(*de))) == NULL) {
73 		assert(0); /* should not happen! */
74 		return false;
75 	}
76 	de->ev = ev;
77 	de->ptr = ptr;
78 	de->next = NULL;
79 
80 	idx = HASHVAL(ev);
81 	if (g_dfTable[idx] == NULL) {
82 		g_dfTable[idx] = de;
83 	}
84 	else  {
85 		p = g_dfTable[idx];
86 		while (p->next)
87 			p = p->next;
88 		p->next = de;
89 	}
90 	return true;
91 }
92 /*----------------------------------------------------------------------------*/
93 static tree_node_t *
94 dforest_search(event_t ev)
95 {
96 	int idx;
97 	struct devent *p;
98 
99 	idx = HASHVAL(ev);
100 	if (g_dfTable[idx] == NULL)
101 		return NULL;
102 
103 	for (p = g_dfTable[idx];
104 	     p != NULL;
105 	     p = p->next) {
106 		if (p->ev == ev)
107 			return p->ptr;
108 	}
109 	return NULL;
110 }
111 /*----------------------------------------------------------------------------*/
112 /** Create a new tree node
113  * @return the new tree node
114  * */
115 inline tree_node_t *
116 tree_node_new()
117 {
118 	return calloc(1, sizeof(tree_node_t));
119 }
120 /*----------------------------------------------------------------------------*/
121 /** Delete a tree node */
122 inline void
123 tree_node_del(tree_node_t *node)
124 {
125 	free(node);
126 }
127 /*----------------------------------------------------------------------------*/
128 /** Delete a tree node and all of its descendants
129  * @param [in] node: target node
130  * */
131 inline void
132 tree_del_recursive(tree_node_t *node)
133 {
134 	struct _tree_node_t *walk = NULL, *del = NULL;
135 	TREE_SCRATCH(_tree_node_t, MAX_DEPTH) stack;
136 
137 	TREE_DFS_FOREACH(walk, node, &stack, link) {
138 		if (del)
139 			tree_node_del(del);
140 		del = walk;
141 	}
142 	if (del)
143 		tree_node_del(del);
144 }
145 /*----------------------------------------------------------------------------*/
146 /** Search a tree node by event ID
147  * @param [in] root: root node
148  * @param [in] ev: event ID
149  * @return target node
150  *
151  * The search is in DFS mannar
152  * */
153 inline tree_node_t *
154 tree_search(tree_node_t *root, event_t ev)
155 {
156 	struct _tree_node_t *walk = NULL;
157 	TREE_SCRATCH(_tree_node_t, MAX_DEPTH) stack;
158 
159 	TREE_DFS_FOREACH(walk, root, &stack, link)
160 		if (walk->ev == ev) {
161 			return walk;
162 		}
163 	return NULL;
164 }
165 /*----------------------------------------------------------------------------*/
166 /** Create a new subtree
167  * @param [in] id: subtree ID
168  * @param [in] root: root of the subtree
169  * @return new subtree
170  *
171  * Allocate and initialize subtree structure, stree_t:
172  *   1. Allocate the structure.
173  *   2. Initialize reference counter and fill ID field.
174  *   3. Set 'root' pointer which points the root node of a tree.
175  *      The tree should contain all required tree nodes.
176  *   4. Set built-in event tree node pointers.
177  * */
178 inline stree_t *
179 stree_create(uint64_t id, tree_node_t *root)
180 {
181 	tree_node_t *bev;
182 	stree_t *nstree = malloc(sizeof(stree_t));
183 	if (!nstree)
184 		return NULL;
185 
186 	nstree->ref_cnt = 0;
187 	nstree->id = id;
188 	nstree->root = root;
189 	memset(nstree->bevs, 0, sizeof(nstree->bevs));
190 
191 	for (bev = TREE_FIRSTBORN(root, link); bev; bev = TREE_YOUNGER(bev, link)) {
192 		int idx = 0;
193 		while (bev->ev >> (idx + 1))
194 			idx++;
195 		nstree->bevs[idx] = bev;
196 	}
197 
198 	return nstree;
199 }
200 /*----------------------------------------------------------------------------*/
201 /** Destroy the subtree
202  * @param [in] stree: the target subtree */
203 inline void
204 stree_destroy(kvs_t *store, stree_t *stree)
205 {
206 	tree_del_recursive(stree->root);
207 	free(stree);
208 }
209 /*----------------------------------------------------------------------------*/
210 /** Increase reference counter of the subtree
211  * @param [in] stree: the target subtree */
212 inline void
213 stree_inc_ref(stree_t *stree)
214 {
215 	stree->ref_cnt++;
216 }
217 /*----------------------------------------------------------------------------*/
218 /** Decrease reference counter of the subtree, and remove it from the key-
219  * value-store if needed
220  * @param [in] store: the key-value-store
221  * @param [in] stree: the target subtree
222  *
223  * In addition to decreasing the reference counter, remove the subtree from
224  * key-value-store if decreased reference counter is zero.
225  * */
226 inline void
227 stree_dec_ref(kvs_t *store, stree_t *stree)
228 {
229 	if (stree && !--stree->ref_cnt) {
230 	  	kvs_remove(store, stree->id);
231 		stree_destroy(store, stree);
232 	}
233 }
234 /*----------------------------------------------------------------------------*/
235 /** Hash the event ID and callback pair
236  * @param [in] ev: the event ID
237  * @param [in] cb: the callback function pointer
238  * @return hash value
239  *
240  * TODO: Replace 32-bit Jenkins hash with better one.
241  * */
242 inline static uint64_t
243 hash64(event_t ev, callback_t cb)
244 {
245 #ifdef NEWHASH
246 	struct {
247 		event_t ev;
248 		callback_t cb;
249 	} instance;
250 
251 	instance.ev = ev;
252 	instance.cb = cb;
253 
254 	return XXH64(&instance, sizeof(event_t) + sizeof(callback_t), XXHSEED);
255 #else
256 	uint64_t hash = 0;
257 	int i;
258 
259 	for (i = 0; i < sizeof(ev); ++i) {
260 		hash += ((uint8_t *)&ev)[i];
261 		hash += (hash << 10);
262 		hash ^= (hash >> 6);
263 	}
264 	for (i = 0; i < sizeof(cb); ++i) {
265 		hash += ((uint8_t *)&cb)[i];
266 		hash += (hash << 10);
267 		hash ^= (hash >> 6);
268 	}
269 	hash += (hash << 3);
270 	hash ^= (hash >> 11);
271 	hash += (hash << 15);
272 
273 	return hash;
274 #endif
275 }
276 
277 /*-------------------------------------------------------------------------*/
278 /* Create a new tree that consists of a tree node (w) with a new
279  * callback and take a snapshot of the subtree from w all the way up to
280  * the root node by traversing the ancestors of w.
281 */
282 /*-------------------------------------------------------------------------*/
283 static tree_node_t*
284 create_spine(tree_node_t* w, callback_t cb)
285 {
286 	tree_node_t *ntn, *ntree = NULL;
287 
288 	if ((ntn = tree_node_new()) == NULL)
289 		return NULL;
290 
291 	/* the leaf event node with callback function */
292 	ntn->ft  = w->ft;
293 	ntn->cb  = cb;
294 	ntn->ev  = w->ev;
295 	ntn->arg = w->arg;
296 	ntree = ntn;          /* we start from the leaf */
297 
298 	do {
299 		if (!(ntn = tree_node_new())) {
300 			if (ntree)
301 				tree_del_recursive(ntree);
302 			return NULL;
303 		}
304 		ntn->ft = w->ft;
305 		ntn->ev = w->ev;
306 		ntn->arg = w->arg;
307 
308 		TREE_INSERT_CHILD(ntn, ntree, link);
309 		if (!IS_FLOATING_EVENT(ntree))
310 			TREE_INSERT_CHILD(ntn, ntree, invk);
311 
312 		/* ntn becomes the new tree */
313 		ntree = ntn;
314 	} while ((w = TREE_PARENT(w, link)));
315 
316 	return ntree;
317 }
318 #if 0
319 /*----------------------------------------------------------------------------*/
320 static stree_t *
321 clone_stree(stree_t * stree)
322 {
323 	stree_t *newstree, *walk;
324 	tree_node_t *newtree;
325 	TREE_SCRATCH(_tree_node_t, MAX_DEPTH) stack;
326 	struct _tree_node_t *walk = NULL, *del = NULL;
327 
328 	/* clone the tree */
329 	TREE_DFS_FOREACH(walk, stree->root, &stack, link) {
330 		new_tree_node_new()
331 			if (del)
332 				tree_node_del(del);
333 		del = walk;
334 	}
335 	if (del)
336 		tree_node_del(del);
337 
338 
339 	TREE_DFS_FOREACH(w, stree->root, &stack, link) {
340 		tree_node_t *ntn, *ptn = NULL;
341 	}
342 }
343 #endif
344 /*----------------------------------------------------------------------------*/
345 /** Register a callback
346  * @param [in] store: the key-value-store for subtrees
347  * @param [in, out] pstree: the target subtree pointer
348  * @param [in] ev: the target event
349  * @param [in] cb: the callback to be registered
350  * @return 0 for success, -1 for failure
351  *
352  * For callback registeration, there can be some cases.
353  *   1. A new tree what we want is already there, so we can use it by simply
354  *      updating reference counters.
355  *   2. A new tree what we want is not there, so we are going to create a
356  *      new subtree. The new subtree will not only have new callback, but also
357  *      inherit previous subtree.
358  *      2.1. The reference counter of previous subtree is 1, so we can avoid
359  *           new tree allocation by reusing tree nodes of previous subtree.
360  *      2.2. The reference counter of previous subtree is not 1, so we should
361  *           copy previous subtree's tree nodes.
362  *   3. Previously, there was no subtree (in other words, this is the first
363  *      callback registeration) so we are going to make a new subtree which
364  *      has only one callback
365  * */
366 inline int
367 RegCb(kvs_t *store, stree_t **pstree, event_t ev, callback_t cb)
368 {
369 #ifdef DBGMSG
370 	__PREPARE_DBGLOGGING();
371 #endif
372 	TRACE_DBG("/>>>>>> start <<<<<<\\\n");
373 	stree_t *stree, *nstree;
374 	TREE_SCRATCH(_tree_node_t, MAX_DEPTH) stack;
375 	tree_node_t *w, *w2, *ntree;
376 	uint64_t id = 0, nid;
377 
378 	if ((stree = *pstree)) {
379 		/* XXX: tree_search() is heavy operation, but it is used for only error
380 		 * checking. Is there any way to avoid this?
381 		 * --> We can have a key-value-store for this, but is it too much? */
382 #if 0
383 		if (tree_search(stree->root, ev))
384 			/* Illegal trial of overwriting a previously registerd callback */
385 			return -1;
386 #endif
387 
388 		id = stree->id;
389 	}
390 
391 	/* calculate new subtree ID */
392 	nid = NEWID(id, ev, cb);
393 
394 	TRACE_DBG("nid: 0x%lX, id: 0x%lx, ev: %ld, cb: %p\n", nid, id, ev, cb);
395 
396 	if ((nstree = kvs_search(store, nid))) {  /* case 1. */
397 		TRACE_DBG("Case 1\n");
398 		/* update reference counters */
399 		if (stree)
400 			stree_dec_ref(store, stree);
401 
402 		nstree->ref_cnt++;
403 		*pstree = nstree;
404 #if 0
405 		fprintf(stderr, "sizeof(tcp_stream)=%ld sizeof(tcp_send_vars)=%ld"
406 			"sizeof(tcp_recv_vars)=%ld\n",
407 			sizeof(tcp_stream),
408 			sizeof(struct tcp_send_vars), sizeof(struct tcp_recv_vars));
409 #endif
410 		return 0;
411 	}
412 
413 	/* find the event node with ev and take a snapshot of the ancestors */
414 	w = dforest_search(ev);
415 	//	w = tree_search(g_evroot, ev);
416 	assert(w);
417 	if ((ntree = create_spine(w, cb)) == NULL)
418 		return (-1);
419 
420 	if (stree) {  /* case 2. */
421 		TRACE_DBG("Case 2\n");
422 		tree_node_t *sptr;
423 
424 		/* attach flesh: Inherit previous subtree */
425 		sptr = ntree;
426 
427 #if 0
428 		/* new code */
429 		if (stree->ref_cnt > 1) {
430 			/* take a snapshot of the entire forest */
431 			curf = clone_tree(stree);
432 			curf->root->ref_cnt = 1;
433 			stree->ref_cnt--;
434 		} else {
435 			assert(stree->ref_cnt == 1);
436 			curf = stree;
437 			/* remove the current id from hash table */
438 			kvs_remove(store, stree->id);
439 		}
440 
441 		/* merge sptr into curf->root (existing tree) */
442 #endif
443 
444 		if (stree->ref_cnt == 1) {
445 			/* case 2.1. */
446 			TRACE_DBG("Case 2.1\n");
447 			w = stree->root;
448 			while (w) {
449 				tree_node_t *next_walk = NULL, *next_walk2 = NULL,
450 					*next_sptr = TREE_FIRSTBORN(sptr, link);
451 
452 				for (w2 = TREE_FIRSTBORN(w, link);
453 				     w2 != NULL;
454 				     w2 = next_walk2) {
455 					next_walk2 = TREE_YOUNGER(w2, link);
456 					if (sptr && w2->ev == next_sptr->ev) {
457 						assert(next_walk == NULL);
458 						next_walk = w2;
459 						if (next_sptr->cb != next_walk->cb)
460 							next_sptr->cb = next_walk->cb;
461 					}
462 					else {
463 						TREE_DETACH(w2, link);
464 						if (!IS_FLOATING_EVENT(w2))
465 							TREE_DETACH(w2, invk);
466 						if (next_walk) {
467 							TREE_INSERT_CHILD(sptr, w2, link);
468 							if (!IS_FLOATING_EVENT(w2))
469 								TREE_INSERT_CHILD(sptr, w2, invk);
470 						} else {
471 							tree_node_t *f = TREE_FIRSTBORN(sptr, link);
472 							TREE_INSERT_OLDER(f, w2, link);
473 							if (!IS_FLOATING_EVENT(w2)) {
474 								if ((f = TREE_FIRSTBORN(sptr, invk)))
475 									TREE_INSERT_OLDER(f, w2, invk);
476 								else
477 									TREE_INSERT_CHILD(sptr, w2, invk);
478 							}
479 						}
480 					}
481 				}
482 				w = next_walk;
483 				sptr = next_sptr;
484 				next_walk = NULL;
485 			}
486 		} else { // stree->ref_count != 1
487 			/* case 2.2. */
488 			TRACE_DBG("Case 2.2\n");
489 			TREE_DFS_FOREACH(w, stree->root, &stack, link) {
490 				tree_node_t *ntn, *ptn = NULL;
491 
492 				if (sptr && w->ev == sptr->ev) {
493 					if (w->cb != sptr->cb)
494 						sptr->cb = w->cb;
495 					sptr = TREE_FIRSTBORN(sptr, link);
496 					continue;
497 				}
498 
499 				if (!(ntn = tree_node_new())) {
500 					if (ntree)
501 						tree_del_recursive(ntree);
502 					return -1;
503 				}
504 				ntn->ft  = w->ft;
505 				ntn->cb  = w->cb;
506 				ntn->ev  = w->ev;
507 				ntn->arg = w->arg;
508 
509 				if (TREE_PARENT(w, link)) {
510 					ptn = tree_search(ntree, TREE_PARENT(w, link)->ev);
511 					assert(ptn);
512 					TREE_INSERT_CHILD(ptn, ntn, link);
513 					if (!IS_FLOATING_EVENT(ntn))
514 						TREE_INSERT_CHILD(ptn, ntn, invk);
515 				} else {
516 					assert(0);
517 				}
518 			}
519 		}
520 	}
521 
522 	/* case 3 if (stree == NULL) */
523 	nstree = stree_create(nid, ntree);
524 	if (nstree == NULL) {
525 		TRACE_ERROR("Failed to create stree!\n");
526 		assert(nstree);
527 	}
528 	nstree->ref_cnt = 1;
529 	kvs_insert(store, nid, nstree);
530 	/* update reference counters */
531 	if (stree)
532 		stree_dec_ref(store, stree);
533 	*pstree = nstree;
534 
535 	TRACE_DBG("\\>>>>>>  end  <<<<<</\n");
536 	return 0;
537 }
538 /*----------------------------------------------------------------------------*/
539 /** Unregister a callback
540  * @param [in] store: the key-value-store for subtrees
541  * @param [in, out] pstree: the target subtree pointer
542  * @param [in] ev: the target event
543  * @return 0 for success, -1 for failure
544  *
545  * For callback unregisteration, there can be some cases.
546  *   1. No registered callback will be left after this unregistration.
547  *   2. A new tree what we want is already there, so we can use it by simply
548  *      updating reference counters.
549  *   3. A new tree what we want is not there, so we create a new subtree by
550  *      copying a part of previous subtree
551  * */
552 inline int
553 UnregCb(kvs_t *store, stree_t **pstree, event_t ev)
554 {
555 #ifdef DBGMSG
556 	__PREPARE_DBGLOGGING();
557 #endif
558 	TRACE_DBG("/>>>>>> start <<<<<<\\\n");
559 	stree_t *stree, *nstree;
560 	TREE_SCRATCH(_tree_node_t, MAX_DEPTH) stack;
561 	tree_node_t *w, *target;
562 	uint64_t id = 0, nid;
563 	callback_t cb;
564 
565 	if (!(stree = *pstree) || !(target = tree_search(stree->root, ev)) ||
566 	    !(cb = target->cb))
567 		/* Illegal trial of unregistering a callback which is never registered
568 		 * before. */
569 		return -1;
570 
571 	id = stree->id;
572 
573 	/* Calculate new subtree ID */
574 	nid = NEWID(id, ev, cb);
575 
576 	TRACE_DBG("nid: 0x%lX, id: 0x%lx, ev: %ld, cb: %p\n",
577 		  nid, id, ev, cb);
578 
579 	if (nid == 0) {
580 		/* case 1. */
581 		TRACE_DBG("Case 1\n");
582 		/* update reference counters */
583 		if (stree)
584 			stree_dec_ref(store, stree);
585 
586 		*pstree = NULL;
587 	} else if ((nstree = kvs_search(store, nid))) {
588 		/* case 2. */
589 		TRACE_DBG("Case 2\n");
590 		/* update reference counters */
591 		if (stree)
592 			stree_dec_ref(store, stree);
593 
594 		nstree->ref_cnt++;
595 		*pstree = nstree;
596 	} else if (stree) {
597 		/* case 3. */
598 		TRACE_DBG("Case 3\n");
599 		bool proceed;
600 		tree_node_t *ntree = NULL, *sptr;
601 
602 		sptr = TREE_PARENT(target, link);
603 #define TREE_IS_ONLY_CHILD(root, x, field) \
604 		(TREE_PARENT((x), field) ?			   \
605 		 TREE_PARENT((x), field)->field.tn_first == (x) && \
606 		 TREE_PARENT((x), field)->field.tn_last == (x) :   \
607 		 (x) == (root) && (x)->field.tn_younger == NULL)
608 		while (sptr && !sptr->cb && TREE_IS_ONLY_CHILD(stree->root, sptr, link))
609 			sptr = TREE_PARENT(sptr, link);
610 
611 		assert(sptr);
612 		/* 'sptr == NULL' means the tree will lose the only callback.
613 		 * This case should be handled by 'Case 1' */
614 
615 		TREE_DFS_FOREACH_SELECTIVE(w, stree->root, &stack, link, proceed) {
616 			tree_node_t *ntn, *ptn;
617 
618 			if (w == sptr)
619 				proceed = false;
620 
621 			if (!(ntn = tree_node_new())) {
622 				/* free incomplete ntree */
623 				if (ntree)
624 					tree_del_recursive(ntree);
625 				return -1;
626 			}
627 			ntn->ft = w->ft;
628 			ntn->cb = w->cb;
629 			ntn->ev = w->ev;
630 			ntn->arg = w->arg;
631 
632 			if (TREE_PARENT(w, link)) {
633 				assert(ntree);
634 				ptn = tree_search(ntree, TREE_PARENT(w, link)->ev);
635 
636 				assert(ptn);
637 
638 				TREE_INSERT_CHILD(ptn, ntn, link);
639 				if (!IS_FLOATING_EVENT(ntn))
640 					TREE_INSERT_CHILD(ptn, ntn, invk);
641 			} else
642 				/* this is the root node */
643 				ntree = ntn;
644 		}
645 
646 		nstree = stree_create(nid, ntree);
647 		if (nstree == NULL) {
648 			TRACE_ERROR("Failed to create stree!\n");
649 			assert(nstree);
650 		}
651 
652 		nstree->ref_cnt = 1;
653 
654 		kvs_insert(store, nid, nstree);
655 
656 		/* update reference counters */
657 		stree_dec_ref(store, stree);
658 
659 		*pstree = nstree;
660 	} else /* if (!stree) */
661 		return -1;
662 
663 	TRACE_DBG("\\>>>>>>  end  <<<<<</\n");
664 	return 0;
665 }
666 /*----------------------------------------------------------------------------*/
667 inline int
668 ModCb(kvs_t *store, stree_t **pstree, event_t ev, callback_t cb)
669 {
670 	assert(*pstree || cb);
671 
672 	/* Event ID starts from 1 */
673 	if (ev == 0)
674 		return -1;
675 
676 	if (cb)
677 		return RegCb(store, pstree, ev, cb);
678 	else
679 		return UnregCb(store, pstree, ev);
680 }
681 /*----------------------------------------------------------------------------*/
682 void
683 GlobInitEvent(void)
684 {
685 	int i;
686 
687 	if (!(g_evroot = tree_node_new())) {
688 		perror("FATAL: Failed to allocate essentials for the system\n");
689 		exit(0);
690 	}
691 	g_evroot->ev = 0;
692 	g_evroot->ft = NULL;
693 	g_evroot->cb = NULL;
694 	TREE_INIT_NODE(g_evroot, link);
695 	TREE_INIT_NODE(g_evroot, invk);
696 	/* add it to the dforest hash table */
697 	dforest_store(g_evroot->ev, g_evroot);
698 	for (i = 0; i < NUM_BEV; i++) {
699 		tree_node_t *ntn;
700 		if (!(ntn = tree_node_new())) {
701 			perror("FATAL: Failed to allocate essentials for the system\n");
702 			exit(0);
703 		}
704 		ntn->ev = 1 << i;
705 		ntn->ft = NULL;
706 		ntn->cb = NULL;
707 		TREE_INIT_NODE(ntn, link);
708 		TREE_INIT_NODE(ntn, invk);
709 		TREE_INSERT_CHILD(g_evroot, ntn, link);
710 		TREE_INSERT_CHILD(g_evroot, ntn, invk);
711 		/* add it to the dforest hash table */
712 		dforest_store(ntn->ev, ntn);
713 	}
714 	g_evid = 1 <<  NUM_BEV;
715 }
716 /*----------------------------------------------------------------------------*/
717 void
718 InitEvent(mtcp_manager_t mtcp)
719 {
720 	mtcp->ev_store = kvs_create(KVS_BUCKETS, KVS_ENTRIES);
721 }
722 /*----------------------------------------------------------------------------*/
723 event_t
724 mtcp_alloc_event(event_t event)
725 {
726 	tree_node_t *parent, *new;
727 
728 	if (!(parent = dforest_search(event)))
729 	//	if (!(parent = tree_search(g_evroot, event)))
730 		return MOS_NULL_EVENT;
731 
732 	if ((new = tree_node_new()) == NULL)
733 		return MOS_NULL_EVENT;
734 
735 	new->ev = g_evid++;
736 	new->ft = NULL;
737 	new->cb = NULL;
738 	new->arg.arg = NULL;
739 	new->arg.len = 0;
740 
741 	TREE_INIT_NODE(new, link);
742 	TREE_INIT_NODE(new, invk);
743 
744 	TREE_INSERT_CHILD(parent, new, link);
745 
746 	return new->ev;
747 }
748 /*----------------------------------------------------------------------------*/
749 event_t
750 mtcp_define_event(event_t event, filter_t filter, struct filter_arg *arg)
751 {
752 #ifdef DBGMSG
753 	__PREPARE_DBGLOGGING();
754 #endif
755 	tree_node_t *parent, *new, *walk;
756 
757 	/* FIX - TODO. This code needs to have proper locking since this
758 	   deals with global variables that are shared across multiple
759 	   threads
760 	*/
761 
762 	if (!filter)
763 		return MOS_NULL_EVENT;
764 	if (arg && arg->len > 0 && !arg->arg)
765 		return MOS_NULL_EVENT;
766 	if (!(parent = dforest_search(event)))
767 	//	if (!(parent = tree_search(g_evroot, event)))
768 		return MOS_NULL_EVENT;
769 	for (walk = TREE_FIRSTBORN(parent, link);
770 	     walk;
771 	     walk = TREE_YOUNGER(walk, link))
772 		if ((walk->ft == filter) &&
773 		    ((walk->arg.arg == NULL && (!arg || !arg->arg || arg->len <= 0)) ||
774 		     (walk->arg.len == arg->len &&
775 		      memcmp(walk->arg.arg, arg->arg, arg->len) == 0)))
776 			return walk->ev;
777 
778 	if ((new = tree_node_new()) == NULL)  {
779 		errno = ENOMEM;
780 		return MOS_NULL_EVENT;
781 	}
782 	new->ev = g_evid++;
783 	new->ft = filter;
784 
785 	/* add it to the dforest hash table */
786 	dforest_store(new->ev, new);
787 
788 	if (arg && arg->arg && arg->len > 0) {
789 		new->arg.arg = malloc(arg->len);
790 		if (new->arg.arg == NULL) {
791 			errno = ENOMEM;
792 			g_evid--;
793 			free(new);
794 			return MOS_NULL_EVENT;
795 		}
796 		memcpy(new->arg.arg, arg->arg, arg->len);
797 		new->arg.len = arg->len;
798 	}
799 
800 	TRACE_DBG("parent: %ld\n", parent->ev);
801 	TREE_INSERT_CHILD(parent, new, link);
802 	TREE_INSERT_CHILD(parent, new, invk);
803 
804 	return new->ev;
805 }
806 /*----------------------------------------------------------------------------*/
807 #define EVENT_STACK_PUSH(s, var)					\
808 	(assert(&(s)->stack[sizeof((s)->stack) / sizeof(void *)] > (s)->sp), \
809 	 *(++((s)->sp)) = (var))
810 #define EVENT_STACK_POP(s)			\
811 	(*(((s)->sp)--))
812 #define EVENT_STACK_CLR(s)				\
813 	((s)->stack[0] = NULL, (s)->sp = (s)->stack)
814 
815 inline int
816 RaiseEv(kvs_t *store, event_t event)
817 {
818 	tree_node_t *ev = NULL;
819 #if 1
820 	struct {
821 		event_t ev;
822 		uint64_t sid;
823 	} instance;
824 
825 	instance.ev = event;
826 	instance.sid = g_cur_stree->id;
827 
828 	_key_t key = XXH64(&instance, sizeof(instance), XXHSEED);
829 	ev = (tree_node_t *)kvs_search(store, key);
830 #else
831 	tree_node_t *walk;
832 	for (walk = TREE_FIRSTBORN(g_cur_ev, link);
833 	     walk;
834 		 walk = TREE_YOUNGER(walk, link)) {
835 		if (walk->ev == event && IS_FLOATING_EVENT(walk)) {
836 			ev = walk;
837 			break;
838 		}
839 	}
840 #endif
841 
842 	if (!ev)
843 		return -1;
844 
845 	if (!ev->is_in_raiseq) {
846 		ev->is_in_raiseq = true;
847 		EVENT_STACK_PUSH(&g_evstack, ev);
848 	}
849 
850 	return 0;
851 }
852 /*----------------------------------------------------------------------------*/
853 int
854 mtcp_raise_event(mctx_t mctx, event_t event)
855 {
856 	mtcp_manager_t mtcp = GetMTCPManager(mctx);
857 	if (!mtcp)
858 		return -1;
859 
860 	return RaiseEv(mtcp->ev_store, event);
861 }
862 /*----------------------------------------------------------------------------*/
863 #define PRINT_EV(event, field)						\
864 	printf("[%s](node: %p) ev: %ld, older: %ld, younger: %ld, child: %ld, " \
865 	       "last: %ld, parent: %ld, ft: %p, cb: %p\n",		\
866 	       #field, (event), (event)->ev,				\
867 	       (event)->field.tn_older   ? (event)->field.tn_older->ev   : -1, \
868 	       (event)->field.tn_younger ? (event)->field.tn_younger->ev : -1, \
869 	       (event)->field.tn_first   ? (event)->field.tn_first->ev   : -1, \
870 	       (event)->field.tn_last    ? (event)->field.tn_last->ev    : -1, \
871 	       (event)->field.tn_parent  ? (event)->field.tn_parent->ev  : -1, \
872 	       (event)->ft, (event)->cb)
873 inline void
874 HandleCb(mctx_t const mctx, int sock, int side,
875 	 stree_t * const stree, event_t events)
876 {
877 	int i;
878 	bool proceed;
879 	tree_node_t *walk, *bev, *ev;
880 	TREE_SCRATCH(_tree_node_t, MAX_DEPTH) queue;
881 	assert(stree);
882 
883 	g_cur_stree = stree;
884 
885 	for (i = 0; i < NUM_BEV; i++) {
886 		if (!((1L << i) & events))
887 			continue;
888 
889 		if (!(bev = stree->bevs[i]))
890 			continue;
891 
892 		EVENT_STACK_CLR(&g_evstack);
893 		tree_node_t **ptr = g_evstack.sp;
894 		TREE_DFS_FOREACH_SELECTIVE(walk, bev, &queue, invk, proceed) {
895 			//PRINT_EV(walk, link);
896 			//PRINT_EV(walk, invk);
897 
898 			g_cur_ev = walk;
899 
900 			if (walk != bev && walk->ft &&
901 			    walk->ft(mctx, sock, side, walk->ev, &walk->arg) == false) {
902 				ptr = g_evstack.sp;
903 				proceed = false;
904 				continue;
905 			}
906 
907 			if (walk->cb)
908 				walk->cb(mctx, sock, side, walk->ev, &walk->arg);
909 
910 			while (ptr < g_evstack.sp) {
911 				ptr++;
912 				TREE_INSERT_CHILD(walk, *ptr, invk);
913 			}
914 		}
915 		g_cur_ev = NULL;
916 
917 		while ((ev = EVENT_STACK_POP(&g_evstack))) {
918 			ev->is_in_raiseq = false;
919 			TREE_DETACH(ev, invk);
920 		}
921 
922 		if (!(events &= ~(1L << i))) {
923 			g_cur_stree = NULL;
924 			return;
925 		}
926 	}
927 
928 	g_cur_stree = NULL;
929 }
930 /*----------------------------------------------------------------------------*/
931 int
932 mtcp_register_callback(mctx_t mctx, int sockid, event_t event,
933 					   int hook_point, callback_t callback)
934 {
935 	socket_map_t socket;
936 	stree_t **pstree;
937 
938 	if (event == MOS_NULL_EVENT ||
939 	    (event < (1L << NUM_BEV) && !POWER_OF_TWO(event)))
940 		return -1;
941 
942 	mtcp_manager_t mtcp = GetMTCPManager(mctx);
943 	if (!mtcp)
944 		return -1;
945 
946 	socket = &mtcp->msmap[sockid];
947 
948 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) {
949 		if (hook_point == MOS_NULL)
950 			pstree = &socket->monitor_stream->stree_dontcare;
951 		else if (hook_point == MOS_HK_RCV)
952 			pstree = &socket->monitor_stream->stree_pre_rcv;
953 		else if (hook_point == MOS_HK_SND)
954 			pstree = &socket->monitor_stream->stree_post_snd;
955 		else
956 			return -1;
957 
958 	} else if (socket->socktype == MOS_SOCK_MONITOR_STREAM
959 		   || socket->socktype == MOS_SOCK_MONITOR_RAW) {
960 		if (hook_point == MOS_NULL)
961 			pstree = &socket->monitor_listener->stree_dontcare;
962 		else if (hook_point == MOS_HK_RCV)
963 			pstree = &socket->monitor_listener->stree_pre_rcv;
964 		else if (hook_point == MOS_HK_SND)
965 			pstree = &socket->monitor_listener->stree_post_snd;
966 		else
967 			return -1;
968 	} else {
969 		errno = EINVAL;
970 		return -1;
971 	}
972 
973 	return ModCb(mtcp->ev_store, pstree, event, callback);
974 }
975 /*----------------------------------------------------------------------------*/
976 int
977 mtcp_unregister_callback(mctx_t mctx, int sockid, event_t event,
978 			 int hook_point)
979 {
980 	return mtcp_register_callback(mctx, sockid, event, hook_point, NULL);
981 }
982 /*----------------------------------------------------------------------------*/
983 inline void
984 HandleCallback(mtcp_manager_t mtcp, uint32_t hook,
985 	       socket_map_t socket, int side, struct pkt_ctx *pctx, event_t events)
986 {
987 	struct sfbpf_program fcode;
988 
989 	if (!socket)
990 		return;
991 
992 	if (!events)
993 		return;
994 	assert(events);
995 
996 	/* if client side monitoring is disabled, then skip */
997 	if (side == MOS_SIDE_CLI && socket->monitor_stream->client_mon == 0)
998 		return;
999 	/* if server side monitoring is disabled, then skip */
1000 	else if (side == MOS_SIDE_SVR && socket->monitor_stream->server_mon == 0)
1001 		return;
1002 
1003 #define MSTRM(sock) (sock)->monitor_stream
1004 #define MLSNR(sock) (sock)->monitor_listener
1005 	/* We use `?:` notation instead of `if/else` to make `evp` as const */
1006 	stree_t * const stree =
1007 		(socket->socktype == MOS_SOCK_MONITOR_STREAM_ACTIVE) ?
1008 		((hook == MOS_HK_RCV) ? MSTRM(socket)->stree_pre_rcv :
1009 		 (hook == MOS_HK_SND) ? MSTRM(socket)->stree_post_snd :
1010 		 MSTRM(socket)->stree_dontcare)
1011 		: (socket->socktype == MOS_SOCK_MONITOR_STREAM)
1012 		|| (socket->socktype == MOS_SOCK_MONITOR_RAW) ?
1013 		((hook == MOS_HK_RCV) ? MLSNR(socket)->stree_pre_rcv :
1014 		 (hook == MOS_HK_SND) ? MLSNR(socket)->stree_post_snd :
1015 		 MLSNR(socket)->stree_dontcare) :
1016 		NULL;
1017 
1018 	if (!stree)
1019 		return;
1020 
1021 	/* mtcp_bind_monitor_filter()
1022 	   - BPF filter is evaluated only for RAW socket and PASSIVE
1023 	   socket (= orphan filter)
1024 	   - stream syn filter is moved to and evaluated on socket creation
1025 	*/
1026 	if (socket->socktype == MOS_SOCK_MONITOR_STREAM) {
1027 		fcode = MLSNR(socket)->stream_orphan_fcode;
1028 		/* if not match with filter, return */
1029 		if (ISSET_BPFFILTER(fcode) && pctx && EVAL_BPFFILTER(fcode,
1030 		    (uint8_t *)pctx->p.iph - sizeof(struct ethhdr),
1031 	        pctx->p.ip_len + sizeof(struct ethhdr)) == 0)
1032 			return;
1033 	}
1034 	if (socket->socktype == MOS_SOCK_MONITOR_RAW) {
1035 		fcode = MLSNR(socket)->raw_pkt_fcode;
1036 		/* if not match with filter, return */
1037 		if (ISSET_BPFFILTER(fcode) && pctx && EVAL_BPFFILTER(fcode,
1038 		    (uint8_t *)pctx->p.iph - sizeof(struct ethhdr),
1039 	        pctx->p.ip_len + sizeof(struct ethhdr)) == 0)
1040 			return;
1041 	}
1042 
1043 	mctx_t const mctx = g_ctx[mtcp->ctx->cpu];
1044 	mtcp->pctx = pctx; /* for mtcp_getcurpkt() */
1045 
1046 	HandleCb(mctx, socket->id, side, stree, events);
1047 }
1048 /*----------------------------------------------------------------------------*/
1049 #endif
1050