diff --git a/WheelTimer/LinkedListApi.c b/WheelTimer/LinkedListApi.c new file mode 100644 index 0000000..8486a2e --- /dev/null +++ b/WheelTimer/LinkedListApi.c @@ -0,0 +1,275 @@ + +#include +#include +#include +#include "LinkedListApi.h" +#include + +ll_t* init_singly_ll(){ + return calloc(1, sizeof(ll_t)); +} + +singly_ll_node_t* singly_ll_init_node(void* data){ + singly_ll_node_t* node = calloc(1, sizeof(singly_ll_node_t)); + node->data = data; + return node; +} + +int +singly_ll_add_node(ll_t* ll, singly_ll_node_t *node){ + if(!ll) return -1; + if(!node) return -1; + if(!GET_HEAD_SINGLY_LL(ll)){ + GET_HEAD_SINGLY_LL(ll) = node; + INC_NODE_COUNT_SINGLY_LL(ll); + return 0; + } + + node->next = GET_HEAD_SINGLY_LL(ll); + GET_HEAD_SINGLY_LL(ll) = node; + INC_NODE_COUNT_SINGLY_LL(ll); + return 0; +} + +int +singly_ll_add_node_by_val(ll_t *ll, void* data){ + singly_ll_node_t* node = singly_ll_init_node(data); + return singly_ll_add_node(ll, node); +} + +int +singly_ll_delete_node(ll_t *ll, singly_ll_node_t *node){ + if(!ll) return -1; + if(!GET_HEAD_SINGLY_LL(ll) || !node) return 0; + singly_ll_node_t *trav = NULL; + /*if node is not the last node*/ + if(node->next){ + singly_ll_node_t *temp = NULL; + node->data = node->next->data; + temp = node->next; + node->next = node->next->next; + free(temp); + DEC_NODE_COUNT_SINGLY_LL(ll); + return 0; + } + + /* if node is the only node in LL*/ + if(ll->node_count == 1 && GET_HEAD_SINGLY_LL(ll) == node){ + free(node); + GET_HEAD_SINGLY_LL(ll) = NULL; + DEC_NODE_COUNT_SINGLY_LL(ll); + return 0; + } + + /*if node is the last node of the LL*/ + trav = GET_HEAD_SINGLY_LL(ll); + while(trav->next != node){ + trav = trav->next; + continue; + } + + trav->next = NULL; + free(node); + DEC_NODE_COUNT_SINGLY_LL(ll); + return 0; +} + +int +singly_ll_remove_node(ll_t *ll, singly_ll_node_t *node){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + if(!node){ + printf("%s(%d) : Error : node is NULL\n", __FUNCTION__, __LINE__); + return -1; + } + int i = 0; + singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll), *prev = NULL; + + if(head == node){ + GET_HEAD_SINGLY_LL(ll) = GET_NEXT_NODE_SINGLY_LL(head); + DEC_NODE_COUNT_SINGLY_LL(ll); + node->next = NULL; + return 0; + } + + prev = head; + head = GET_NEXT_NODE_SINGLY_LL(head); + for(i =1; i < GET_NODE_COUNT_SINGLY_LL(ll); i++){ + if(head != node){ + prev = head; + head = GET_NEXT_NODE_SINGLY_LL(head); + continue; + } + + prev->next = GET_NEXT_NODE_SINGLY_LL(head); + GET_NEXT_NODE_SINGLY_LL(head) = NULL; + DEC_NODE_COUNT_SINGLY_LL(ll); + node->next = NULL; + return 0; + } + printf("%s(%d) : Error : node not found\n", __FUNCTION__, __LINE__); + return -1; +} + + + +unsigned int +singly_ll_delete_node_by_value(ll_t *ll, void *data, int size){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll); + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + while(trav != NULL){ + if(memcmp(trav->data, data, size) == 0){ + singly_ll_delete_node(ll, trav); + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); + } + trav = trav->next; + } + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); +} + + +unsigned int +singly_ll_remove_node_by_value(ll_t *ll, void *data, int size){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0; + unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll); + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + while(trav != NULL){ + if(memcmp(trav->data, data, size) == 0){ + singly_ll_remove_node(ll, trav); + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); + } + trav = trav->next; + } + return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll); +} + +singly_ll_node_t* +singly_ll_get_node_by_data_ptr(ll_t *ll, void *data){ + if(!ll || !GET_HEAD_SINGLY_LL(ll)) return NULL; + int i = 0; + singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll); + + for(; i < GET_NODE_COUNT_SINGLY_LL(ll); i++){ + if(head->data == data) + return head; + head = GET_NEXT_NODE_SINGLY_LL(head); + } + return NULL; +} + + +void print_singly_LL(ll_t *ll){ + if(!ll) { + printf("Invalid Linked List\n"); + return; + } + if(is_singly_ll_empty(ll)){ + printf("Empty Linked List\n"); + return; + } + + singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll); + unsigned int i = 0; + printf("node count = %d\n", GET_NODE_COUNT_SINGLY_LL(ll)); + while(trav){ + printf("%d. Data = %p, node = %p\n", i, trav->data, trav); + i++; + trav = trav->next; + } +} + +bool_t +is_singly_ll_empty(ll_t *ll){ + if(!ll) assert(0); + if(ll->node_count == 0) + return LL_TRUE; + return LL_FALSE; +} + +void +reverse_singly_ll(ll_t *ll){ + if(!ll) assert(0) ; + if(is_singly_ll_empty(ll)) return; + if(GET_NODE_COUNT_SINGLY_LL(ll) == 1) return; + singly_ll_node_t *p1 = GET_HEAD_SINGLY_LL(ll), + *p2 = ll->head->next, *p3 = NULL; + p1->next = NULL; + do{ + p3 = p2->next; + p2->next = p1; + p1 = p2; + p2 = p3; + }while(p3); + ll->head = p1; + return; +} + +void +delete_singly_ll(ll_t *ll){ + if(!ll) return; + + if(is_singly_ll_empty(ll)){ + return; + } + + singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll), + *next = GET_NEXT_NODE_SINGLY_LL(head); + + do{ + free(head); + head = next; + if(next) + next = GET_NEXT_NODE_SINGLY_LL(next); + + } while(head); + + ll->node_count = 0; + ll->head = NULL; +} + + + + +#if 0 +int +main(int argc, char **argv){ + ll_t* list = init_singly_ll(); + int n1 = 1; + singly_ll_add_node_by_val(list, &n1); +#if 1 + int n2 =2; + singly_ll_add_node_by_val(list, &n2); + int n3 =3; + singly_ll_add_node_by_val(list, &n3); + int n4 =4; + singly_ll_add_node_by_val(list, &n4); + int n5 =5; + singly_ll_add_node_by_val(list, &n5); + int n6 =6; + singly_ll_add_node_by_val(list, &n6); + int n7 =7; + singly_ll_add_node_by_val(list, &n7); + int n8 = 8; + singly_ll_add_node_by_val(list, &n8); + int n9 = 9; + singly_ll_add_node_by_val(list, &n9); + int n10 = 10; + singly_ll_add_node_by_val(list, &n10); +#endif + print_singly_LL(list); + +#if 1 + int n = 5; + unsigned int num_nodes_removed = singly_ll_remove_node_by_value(list, &n, sizeof(int)); + printf("number of noded removed = %d\n", num_nodes_removed); + print_singly_LL(list); +#endif + n = 1; + singly_ll_remove_node_by_value(list, &n, sizeof(int)); + //reverse_singly_ll(list); + print_singly_LL(list); + + return 0; + +} +#endif diff --git a/WheelTimer/LinkedListApi.h b/WheelTimer/LinkedListApi.h new file mode 100644 index 0000000..da4afb5 --- /dev/null +++ b/WheelTimer/LinkedListApi.h @@ -0,0 +1,39 @@ +#ifndef __LINKEDLIST__ +#define __LINKEDLIST__ + + +#define GET_HEAD_SINGLY_LL(ll) (ll->head) +#define INC_NODE_COUNT_SINGLY_LL(ll) (ll->node_count++) +#define DEC_NODE_COUNT_SINGLY_LL(ll) (ll->node_count--) +#define GET_NODE_COUNT_SINGLY_LL(ll) (ll->node_count) +#define GET_NEXT_NODE_SINGLY_LL(node) (node->next) + +typedef enum{ + LL_FALSE, + LL_TRUE +} bool_t; + +typedef struct LL_Node{ + void *data; + struct LL_Node *next; +} singly_ll_node_t; + +typedef struct LL{ + unsigned int node_count; + singly_ll_node_t *head; +} ll_t; + +ll_t* init_singly_ll(); +singly_ll_node_t* singly_ll_init_node(void* data); +int singly_ll_add_node(ll_t *ll, singly_ll_node_t *node); +int singly_ll_add_node_by_val(ll_t *ll, void* data); +int singly_ll_remove_node(ll_t *ll, singly_ll_node_t *node); +unsigned int singly_ll_remove_node_by_value(ll_t *ll, void* data, int size); +bool_t is_singly_ll_empty(ll_t *ll); +void print_singly_LL(ll_t *ll); +void reverse_singly_ll(ll_t *ll); +void delete_singly_ll(ll_t *ll); +int singly_ll_delete_node(ll_t *ll, singly_ll_node_t *node); +unsigned int singly_ll_delete_node_by_value(ll_t *ll, void *data, int size); +singly_ll_node_t *singly_ll_get_node_by_data_ptr(ll_t *ll, void *data); +#endif diff --git a/WheelTimer/Makefile b/WheelTimer/Makefile new file mode 100644 index 0000000..e5fa440 --- /dev/null +++ b/WheelTimer/Makefile @@ -0,0 +1,14 @@ +LIBS=-lpthread +CC=gcc +CFLAGS=-Wall -g +INCLUDES=-I . +SRC=WheelTimer.o threadApi.o main.o LinkedListApi.o +TARGET:exe +%.o:%.c + ${CC} ${CFLAGS} -c ${INCLUDES} $< +exe:$(SRC) + ${CC} ${CFLAGS} $(SRC) -o exe $(LIBS) +clean: + rm *.o + rm exe + diff --git a/WheelTimer/WheelTimer.c b/WheelTimer/WheelTimer.c new file mode 100644 index 0000000..7dabc73 --- /dev/null +++ b/WheelTimer/WheelTimer.c @@ -0,0 +1,190 @@ +#include "WheelTimer.h" +#include +#include +#include +#include +#include +#include "LinkedListApi.h" + +#define TH_JOINABLE 1 +#define TH_DETACHED 0 + +extern blocked_pool_t gl_blocked_th_pool; + +wheel_timer_t* +init_wheel_timer(int wheel_size, int clock_tic_interval){ + wheel_timer_t *wt = calloc(1, sizeof(wheel_timer_t) + + wheel_size*sizeof(ll_t *)); + + wt->clock_tic_interval = clock_tic_interval; + wt->wheel_size = wheel_size; + + pthread_mutex_init(&wt->wheel_timer_mutex, NULL); + wt->wheel_thread = calloc(1, sizeof(_pthread_t)); + pthread_init(wt->wheel_thread, 0, TH_DETACHED); + + int i = 0; + for(; i < wheel_size; i++) + wt->slots[i] = init_singly_ll(); + + return wt; +} + + +static void* +wheel_fn(void *arg){ + + wheel_timer_t *wt = (wheel_timer_t *)arg; + wheel_timer_elem_t *wt_elem = NULL; + int absolute_slot_no = 0, i =0; + ll_t *slot_list = NULL; + singly_ll_node_t *head = NULL, *next_node = NULL; + + while(1){ + wt->current_clock_tic++; + wt->current_clock_tic = (wt->current_clock_tic % wt->wheel_size); + if(wt->current_clock_tic == 0) + wt->current_cycle_no++; + + sleep(wt->clock_tic_interval); + tentative_wait(wt->wheel_thread, &wt->wheel_timer_mutex); + + slot_list = wt->slots[wt->current_clock_tic]; + head = GET_HEAD_SINGLY_LL(slot_list); + int node_count = GET_NODE_COUNT_SINGLY_LL(slot_list); + absolute_slot_no = GET_WT_CURRENT_ABS_SLOT_NO(wt); + printf("Wheel Timer Time = %d : ", absolute_slot_no * wt->clock_tic_interval); + if(!node_count) + printf("\n"); + for(i = 0; i < node_count; i++){ + next_node = GET_NEXT_NODE_SINGLY_LL(head); + wt_elem = (wheel_timer_elem_t *)head->data; + if(wt->current_cycle_no == wt_elem->execute_cycle_no){ + wt_elem->app_callback(wt_elem->arg, wt_elem->arg_size); + if(wt_elem->is_recurrence){ + /*relocate*/ + int next_abs_slot_no = absolute_slot_no + (wt_elem->time_interval/wt->clock_tic_interval); + int next_cycle_no = next_abs_slot_no / wt->wheel_size; + int next_slot_no = next_abs_slot_no % wt->wheel_size; + wt_elem->execute_cycle_no = next_cycle_no; + if(next_slot_no == wt->current_clock_tic){ + head = next_node; + continue; + } + singly_ll_remove_node(slot_list, head); + singly_ll_add_node(wt->slots[next_slot_no], head); + } + else{ + free_wheel_timer_element((wheel_timer_elem_t *)head->data); + singly_ll_delete_node(slot_list, head); + } + } + head = next_node; + } + } + return NULL; +} + +void +register_app_event(wheel_timer_t *wt, + app_call_back call_back, + void *arg, + int arg_size, + int time_interval, + char is_recursive){ + + if(!wt || !call_back) return ; + wheel_timer_elem_t *wt_elem = calloc(1, sizeof(wheel_timer_elem_t)); + + wt_elem->time_interval = time_interval; + wt_elem->app_callback = call_back; + wt_elem->arg = calloc(1, arg_size); + memcpy(wt_elem->arg, arg, arg_size); + wt_elem->arg_size = arg_size; + wt_elem->is_recurrence = is_recursive; + + /*Stop the Wheel timer Thread here*/ + pause_wheel_timer(wt); + + int wt_absolute_slot = GET_WT_CURRENT_ABS_SLOT_NO(wt); + int registration_next_abs_slot = wt_absolute_slot + (wt_elem->time_interval/wt->clock_tic_interval); + int cycle_no = registration_next_abs_slot / wt->wheel_size; + int slot_no = registration_next_abs_slot % wt->wheel_size; + wt_elem->execute_cycle_no = cycle_no; + singly_ll_add_node_by_val(wt->slots[slot_no], wt_elem); + //printf("Wheel Timer snapshot on New Registration\n"); + //print_wheel_timer(wt); + + resume_wheel_timer(wt); +} + +void +free_wheel_timer_element(wheel_timer_elem_t *wt_elem){ + free(wt_elem->arg); + free(wt_elem); +} + + +void +print_wheel_timer(wheel_timer_t *wt){ + int i = 0, j = 0; + ll_t* slot_list = NULL; + wheel_timer_elem_t *wt_elem = NULL; + singly_ll_node_t *head = NULL; + + printf("Printing Wheel Timer DS\n"); + printf("wt->current_clock_tic = %d\n", wt->current_clock_tic); + printf("wt->clock_tic_interval = %d\n", wt->clock_tic_interval); + printf("wt->wheel_size = %d\n", wt->wheel_size); + printf("wt->current_cycle_no = %d\n", wt->current_cycle_no); + printf("wt->wheel_thread = %p\n", wt->wheel_thread); + printf("printing slots : \n"); + + for(; i < wt->wheel_size; i++){ + slot_list = wt->slots[i]; + printf(" slot_list[%d] : count : %d\n", i, GET_NODE_COUNT_SINGLY_LL(slot_list)); + head = GET_HEAD_SINGLY_LL(slot_list); + for(j = 0 ; j < GET_NODE_COUNT_SINGLY_LL(slot_list); j++){ + wt_elem = (wheel_timer_elem_t *)head->data; + if(!wt_elem){ + printf(" NULL\n"); + head = GET_NEXT_NODE_SINGLY_LL(head); + continue; + } + printf(" wt_elem->time_interval = %d\n", wt_elem->time_interval); + printf(" wt_elem->execute_cycle_no = %d\n", wt_elem->execute_cycle_no); + printf(" wt_elem->app_callback = %p\n", wt_elem->app_callback); + printf(" wt_elem->arg = %p\n", wt_elem->arg); + printf(" wt_elem->is_recurrence = %d\n", wt_elem->is_recurrence); + head = GET_NEXT_NODE_SINGLY_LL(head); + } + } +} + + +void +start_wheel_timer(wheel_timer_t *wt){ + + _pthread_t *thread = wt->wheel_thread; + if (pthread_create(&thread->pthread_handle, &thread->attr, wheel_fn, (void*)wt)) + { + printf("Wheel Timer Thread initialization failed, exiting ... \n"); + exit(0); + } +} + +void +reset_wheel_timer(wheel_timer_t *wt){ + wt->current_clock_tic = 0; + wt->current_cycle_no = 0; +} + +void +pause_wheel_timer(wheel_timer_t *wt){ + send_wait_order(wt->wheel_thread); +} + +void +resume_wheel_timer(wheel_timer_t *wt){ + signal_t(wt->wheel_thread); +} diff --git a/WheelTimer/WheelTimer.h b/WheelTimer/WheelTimer.h new file mode 100644 index 0000000..9e9a82b --- /dev/null +++ b/WheelTimer/WheelTimer.h @@ -0,0 +1,72 @@ +#ifndef __WHEEL_TIMER__ +#define __WHEEL_TIMER__ +#include "threadApi.h" + +typedef struct _wheel_timer_elem_t wheel_timer_elem_t; +typedef void (*app_call_back)(void *arg, int sizeof_arg); +typedef struct LL ll_t; + +struct _wheel_timer_elem_t{ + int time_interval; + int execute_cycle_no; + app_call_back app_callback; + void *arg; + int arg_size; + char is_recurrence; +}; + + +typedef struct _wheel_timer_t { + int current_clock_tic; + int clock_tic_interval; + int wheel_size; + int current_cycle_no; + _pthread_t *wheel_thread; + pthread_mutex_t wheel_timer_mutex; + ll_t *slots[0]; +} wheel_timer_t; + +wheel_timer_t* +init_wheel_timer(int wheel_size, int clock_tic_interval); + +#define GET_WT_CURRENT_ABS_SLOT_NO(wt) ((wt->current_cycle_no * wt->wheel_size) + wt->current_clock_tic) + +void +cleanup_wheel_timer(wheel_timer_t *wt); + +void +register_app_event(wheel_timer_t *wt, + app_call_back call_back, + void *arg, + int arg_size, + int time_interval, + char is_recursive); + +int +unregister_app_event(wheel_timer_t *wt, + app_call_back call_back, + int time_interval); + + +void +free_wheel_timer_element(wheel_timer_elem_t *wt_elem); + +void +print_wheel_timer(wheel_timer_t *wt); + +void +start_wheel_timer(wheel_timer_t *wt); + +void +pause_wheel_timer(wheel_timer_t *wt); + +void +cancel_wheel_timer(wheel_timer_t *wt); + +void +reset_wheel_timer(wheel_timer_t *wt); + +void +resume_wheel_timer(wheel_timer_t *wt); + +#endif diff --git a/WheelTimer/main.c b/WheelTimer/main.c new file mode 100644 index 0000000..4ddeaaa --- /dev/null +++ b/WheelTimer/main.c @@ -0,0 +1,143 @@ +#include "WheelTimer.h" +#include +#include +#include + + +#define MAX_NUMBER_APP_THREADS 1 +#define WHEEL_SIZE 15 +#define WHEEL_TIMER_CLOCK_TIC_INTERVAL 1 // sec + +/*Import Library global Variables*/ +extern blocked_pool_t gl_blocked_th_pool; + +void +generate_general_query(int vlan){ + static int count = 0; + printf("%s() : Query no : %d : general query is generated for vlan %d\n", __FUNCTION__, count++, vlan); +} + +void wrapper_generate_general_query(void *arg, int arg_size){ + + int vlan = *(int *)arg; + generate_general_query(vlan); +} + +void +generate_pim_hello(int vlan){ + static int count = 0; + printf("%s() : Query no : %d : pim_hello is generated for vlan %d\n", __FUNCTION__, count++, vlan); +} + +void +wrapper_generate_pim_hello(void *arg, int arg_size){ + int vlan = *(int *)arg; + generate_pim_hello(vlan); +} + +void +generate_ospf_hello(int vlan){ + static int count = 0; + printf("%s() : Query no : %d : ospf_hello is generated for vlan %d\n", __FUNCTION__, count++, vlan); +} + +void wrapper_generate_ospf_hello(void *arg, int arg_size){ + + int vlan = *(int *)arg; + generate_ospf_hello(vlan); +} + +void +main_menu(wheel_timer_t *wt){ + do{ + printf("\nMain Menu\n"); + printf("*************\n"); + printf("1. dump Wheel Timer\n"); + printf("2. Register General Query Event\n"); + printf("3. Register Pim Hello Event\n"); + printf("4. Register Ospf Hello Event\n"); + printf("5. Reset Wheel Timer\n"); + printf("6. Exit\n"); + int choice; + scanf("%d", &choice); + switch(choice){ + case 1: + print_wheel_timer(wt); + break; + case 2: + { + int vlan_no; + printf("Enter vlan no : "); + scanf("%d", &vlan_no); + char is_recursive; + printf("Is Recirsive (1/0) ? "); + scanf("%d", (int *)&is_recursive); + int time_interval; + printf("time_interval ? "); + scanf("%d", &time_interval); + register_app_event(wt, wrapper_generate_general_query, + (void *)&vlan_no, sizeof(vlan_no), time_interval, is_recursive); + + } + break; + case 3: + { + int vlan_no; + printf("Enter vlan no : "); + scanf("%d", &vlan_no); + char is_recursive; + printf("Is Recirsive (1/0) ? "); + scanf("%d", (int *)&is_recursive); + int time_interval; + printf("time_interval ? "); + scanf("%d", &time_interval); + register_app_event(wt, wrapper_generate_pim_hello, + (void *)&vlan_no, sizeof(vlan_no), time_interval, is_recursive); + + } + break; + case 4: + { + int vlan_no; + printf("Enter vlan no : "); + scanf("%d", &vlan_no); + char is_recursive; + printf("Is Recirsive (1/0) ? "); + scanf("%d", (int *)&is_recursive); + int time_interval; + printf("time_interval ? "); + scanf("%d", &time_interval); + register_app_event(wt, wrapper_generate_ospf_hello, + (void *)&vlan_no, sizeof(vlan_no), time_interval, is_recursive); + + } + break; + + case 5: + reset_wheel_timer(wt); + break; + case 6: + exit(0); + default: + break; + + } + } + while(1); +} + +int +main(int argc, char **argv){ + + init_blocked_pool(&gl_blocked_th_pool, MAX_NUMBER_APP_THREADS); + wheel_timer_t *wt = + init_wheel_timer(WHEEL_SIZE, WHEEL_TIMER_CLOCK_TIC_INTERVAL); + start_wheel_timer(wt); + + /* WT thread is in DETACHED MODE, so below call is useless*/ + //pthread_join(wt->wheel_thread->pthread_handle, &ret_val); + + main_menu(wt); + return 0; +} + diff --git a/WheelTimer/readme b/WheelTimer/readme new file mode 100644 index 0000000..e512f97 --- /dev/null +++ b/WheelTimer/readme @@ -0,0 +1,7 @@ +This is the simple demostration of WheelTimer in C + +you should have gcc compiler installed to compile the project. + +run 'make' to compile the project + +run ./exe to launch the application diff --git a/WheelTimer/threadApi.c b/WheelTimer/threadApi.c new file mode 100644 index 0000000..e115601 --- /dev/null +++ b/WheelTimer/threadApi.c @@ -0,0 +1,216 @@ +#include "threadApi.h" +#include +#include + +blocked_pool_t gl_blocked_th_pool; + + +_pthread_t* +get_blocked_thread_from_pool(blocked_pool_t *block_pool){ + int i ; + for (i = block_pool->pool_size -1; i >=0; i--){ + if(block_pool->blocked_thread_collection[i]) + return block_pool->blocked_thread_collection[i]; + } + return NULL; +} + +void +dump_block_pool(blocked_pool_t *block_pool){ + printf("pool size = %d\n", block_pool->pool_size); + unsigned int i = 0; + for(;i < block_pool->pool_size; i++){ + if(block_pool->blocked_thread_collection[i]){ + printf("pool[%d] = %d\n", i, block_pool->blocked_thread_collection[i]->selfid); + dump_thread_DS(block_pool->blocked_thread_collection[i]); + } + else + printf("block_pool->blocked_thread_collection[%d] = NULL\n", i ); + } + return; +} + +int +is_thread_in_block_pool(unsigned int thid, blocked_pool_t *block_pool){ + int i ; + for (i = 0; i < block_pool->pool_size; i++) + { + if(block_pool->blocked_thread_collection[i] && + block_pool->blocked_thread_collection[i]->selfid == thid){ + return i; + } + } + return FAILURE; +} + + +int +is_thread_in_block_pool_mutex(unsigned int thid, blocked_pool_t *block_pool){ + int i ; + pthread_mutex_lock(&(block_pool->pool_mutex)); + for (i = 0; i < block_pool->pool_size; i++) + { + if(block_pool->blocked_thread_collection[i] && + block_pool->blocked_thread_collection[i]->selfid == thid){ + pthread_mutex_unlock(&(block_pool->pool_mutex)); + return i; + } + } + pthread_mutex_unlock(&(block_pool->pool_mutex)); + return FAILURE; +} + +void +init_blocked_pool(blocked_pool_t *block_pool, unsigned int pool_size){ + int i = 0; + block_pool->pool_size = pool_size; + for (i = 0; i < pool_size; i++) + block_pool->blocked_thread_collection[i] = NULL; + pthread_mutex_init(&(block_pool->pool_mutex), NULL); + return; +} + +int +get_empty_slot_from_pool(blocked_pool_t *block_pool){ + int i; + for(i = block_pool->pool_size -1; i >=0; i--){ + if(block_pool->blocked_thread_collection[i] == NULL) + return i; + } + return FAILURE; +} + + +int +get_empty_slot_from_pool_mutex(blocked_pool_t *block_pool){ + int i; + pthread_mutex_lock(&(block_pool->pool_mutex)); + for(i = block_pool->pool_size -1; i >=0; i--){ + if(block_pool->blocked_thread_collection[i] == NULL) + pthread_mutex_unlock(&(block_pool->pool_mutex)); + return i; + } + pthread_mutex_unlock(&(block_pool->pool_mutex)); + return FAILURE; +} + +int +remove_thread_from_pool(blocked_pool_t *block_pool, _pthread_t *thread){ + int loc = -1; + if(thread->selfid > (block_pool->pool_size - 1)) return FAILURE; + pthread_mutex_lock(&(block_pool->pool_mutex)); + if((loc = is_thread_in_block_pool(thread->selfid, block_pool)) > -1) + { + block_pool->blocked_thread_collection[loc] = NULL; + printf("thread %d is removed from gl_blocked_th_pool\n", thread->selfid); + } + else + { + printf("thread %d already does not exist in gl_blocked_th_pool\n", thread->selfid); + } + pthread_mutex_unlock(&(block_pool->pool_mutex)); + return loc; +} + +void +dump_thread_DS(_pthread_t *thread) +{ + printf("===================================\n"); + printf("selfid = %d\n", thread->selfid); + printf("pthread_handle = %ld\n", thread->pthread_handle); + printf("isWaiting = %d\n", thread->isWaiting); + printf("resume_thread_id = %d\n", thread->resume_thread_id); + printf("attr = 0x%x\n", (unsigned int )&(thread->attr)); + printf("cond = 0x%x\n", (unsigned int )&(thread->cond)); + printf("===================================\n"); + return; +} + +static int +_pool_add(blocked_pool_t *block_pool, _pthread_t *thread) +{ + int loc = -1; + if(thread->selfid > block_pool->pool_size -1) return -1; + loc = get_empty_slot_from_pool(block_pool); + if(loc > -1){ + block_pool->blocked_thread_collection[loc] = thread; + printf("thread %d is added to gl_blocked_th_pool at index %d\n", thread->selfid, loc); + return loc; + } + else{ + printf("gl_blocked_th_pool is full, thread %d cannot be added\n", thread->selfid); + return FAILURE; + } +} + +int +add_thread_to_pool(blocked_pool_t *block_pool , _pthread_t *thread) +{ + if (!block_pool) return -1; + int rc = SUCCESS; + pthread_mutex_lock(&block_pool->pool_mutex); + + if(is_thread_in_block_pool(thread->selfid, block_pool) < 0) + { + rc = _pool_add(block_pool, thread); + pthread_mutex_unlock(&block_pool->pool_mutex); + return rc; + } + else + { + printf("Thread %d is already in blocked pool\n", thread->selfid); + pthread_mutex_unlock(&block_pool->pool_mutex); + return FAILURE; + } +} + +void pthread_init(_pthread_t *_pthread, unsigned int tid, unsigned int JOINABLE) +{ + _pthread->selfid = tid; + pthread_attr_init(&_pthread->attr); + JOINABLE ? pthread_attr_setdetachstate(&_pthread->attr, PTHREAD_CREATE_JOINABLE): + pthread_attr_setdetachstate(&_pthread->attr, PTHREAD_CREATE_DETACHED); + pthread_cond_init(&_pthread->cond, NULL); + _pthread->isWaiting = FALSE; + _pthread->resume_thread_id = -1; +} + +void cleanup_pthread(_pthread_t *thread) +{ + pthread_attr_destroy(&(thread->attr)); + pthread_cond_destroy(&(thread->cond)); + return; +} + +void +wait_t (_pthread_t *thread_to_block, pthread_mutex_t *mutex, unsigned int line_no){ + pthread_mutex_lock(mutex); + thread_to_block->isWaiting = TRUE; + if(pthread_cond_wait (&(thread_to_block->cond), mutex)){ + printf("pthread_cond_wait failed, thread id = %d, line_no = %d", thread_to_block->selfid, line_no); + thread_to_block->isWaiting = FALSE; + pthread_exit(NULL); + } + pthread_mutex_unlock(mutex); +} + +void +signal_t (_pthread_t *signalled_thread){ + remove_thread_from_pool(&gl_blocked_th_pool, signalled_thread); + if(pthread_cond_signal(&(signalled_thread->cond))){ + pthread_exit(NULL); + } + signalled_thread->isWaiting = FALSE; + signalled_thread->resume_thread_id = 0; +} + +void tentative_wait(_pthread_t *thread, pthread_mutex_t *mutex){ + if(is_thread_in_block_pool_mutex(0, &gl_blocked_th_pool) > -1) + wait_t(thread, mutex, __LINE__); + +} + +void +send_wait_order(_pthread_t *thread){ + add_thread_to_pool(&gl_blocked_th_pool, thread); +} diff --git a/WheelTimer/threadApi.h b/WheelTimer/threadApi.h new file mode 100644 index 0000000..7f6f874 --- /dev/null +++ b/WheelTimer/threadApi.h @@ -0,0 +1,87 @@ +#ifndef __PTHREAD__ +#define __PTHREAD__ + +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#ifndef FAILURE +#define FAILURE -1 +#endif + +#define MAX_POOL_SIZE 100 + +typedef struct _pthread_t_{ + pthread_t pthread_handle; + unsigned int selfid; + char isWaiting; + unsigned int resume_thread_id; + pthread_attr_t attr; + pthread_cond_t cond; +} _pthread_t; + +typedef struct _pool_blocked_threads_{ + unsigned int pool_size; + _pthread_t* blocked_thread_collection[MAX_POOL_SIZE]; + pthread_mutex_t pool_mutex; +} blocked_pool_t; + +void +dump_block_pool(blocked_pool_t *block_pool); + +int +is_thread_in_block_pool(unsigned int thid, blocked_pool_t *block_pool); + + +int +is_thread_in_block_pool_mutex(unsigned int thid, blocked_pool_t *block_pool); + +void +init_blocked_pool(blocked_pool_t *block_pool, unsigned int pool_size); + +int +get_empty_slot_from_pool(blocked_pool_t *block_pool); + +int +get_empty_slot_from_pool_mutex(blocked_pool_t *block_pool); + +_pthread_t* +get_blocked_thread_from_pool(blocked_pool_t *block_pool); + +int +remove_thread_from_pool(blocked_pool_t *block_pool , _pthread_t *thread); + +int +add_thread_to_pool(blocked_pool_t *block_pool, _pthread_t *thread); + +void +send_wait_order(_pthread_t *thread); + +void +dump_thread_DS(_pthread_t *thread); + +void +wait_t (_pthread_t *thread_to_block, pthread_mutex_t *mutex, unsigned int line_no); + +void +signal_t (_pthread_t *signalled_thread); + +void +pthread_init(_pthread_t *_pthread, unsigned int tid, unsigned int JOINABLE); + +void +cleanup_pthread(_pthread_t *thread); + +void tentative_wait(_pthread_t *thread, pthread_mutex_t *mutex); + +#endif