/*************************************************************************************************** * Copyright (C) Vasiliy Kosenko (vkos), 2009 * * Kobra is free software: you can redistribute it and/or modify it under the terms of the GNU * * General Public License as published by the Free Software Foundation, either version 3 * * of the License, or (at your option) any later version. * * * * Kobra is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License along with Kobra. * * If not, see . * ***************************************************************************************************/ /*************************************************************************************************** * Kobra (Kolibri Bus for Reaching Applications) is daemon for advanced & easier applications * * communication. * ***************************************************************************************************/ #include "kobra.h" #include #include #include #include #include #include group_list_t *main_group_list; thread_list_t *main_thread_list; kolibri_memarea_t main_memarea; Heap memarea_heap; void *return_0(Heap *wheap, int nbytes){ return NULL; } void *memarea_alloc(int nbytes){ return halMemAlloc(&memarea_heap, nbytes); } void memarea_free(void *addr){ halMemFree(&memarea_heap, addr); } void main(){ malloc_init(); // Alloc memory for thread&group lists main_memarea = kolibri_new_named_memory(KOBRA_MEMAREA_NAME, KOBRA_MEM_SIZE, KOLIBRI_ACCESS_READ|KOLIBRI_CREATE); halMemHeapInit(&memarea_heap, &return_0, main_memarea.addr, KOBRA_MEM_SIZE); // Init main group list create_group("main"); main_group_list->next = main_group_list->previos = main_group_list; main_group_list->thread_list = main_thread_list = new_thread_list(kolibri_get_my_tid()); main_thread_list->next = main_thread_list->previos = main_thread_list; IPCInit(); // kolibri_IPC_unlock(); // Set event mask // kolibri_event_set_mask(KOLIBRI_IPC_EVENT_MASK); while (1) { Message *msg = IPCWaitMessage(-1); // if (kolibri_event_wait() != KOLIBRI_IPC_EVENT) { // Just ignore this error // continue; // } message_handle(msg); free(msg); // kolibri_IPC_clear_buff(); } } void message_handle(kolibri_IPC_message_t *message){ char *msg = (char *)message+sizeof(kolibri_IPC_message_t); char cmd = msg[0]; thread_list_t *thread = find_tid(main_group_list, message->tid); group_list_t *group; int i; if (cmd == KOBRA_CMD_REGISTER && !thread) { kobra_register(message->tid); } else if (thread) { switch (cmd) { case KOBRA_CMD_JOIN: if (message->length < 3 || msg[message->length-1] != '\0') { // Here should be some error handler return; } if (!(group = find_group(msg+1))){ group = create_group(msg+1); } add_to_group(group, message->tid); break; case KOBRA_CMD_UNJOIN: if (message->length < 3 || msg[message->length-1] != '\0') { // Here should be some error handler return; } if ((group = find_group(msg+1)) && (thread = find_tid(group, message->tid))) { remove_from_group(group, thread); } break; case KOBRA_CMD_SEND: if (message->length < 4) { // Here should be some error handler return; } // Check if group name is correct for (i = 1; i < message->length-1 && msg[i]; ++i); if (msg[i]) { // Here should be some error handler return; } group = find_group(msg+1); if (!group) { // Here should be some error handler return; } send_group_message(group, message->tid, msg+i+1, message->length-i-1); break; case KOBRA_CMD_GET_LIST_NAME: // This is temporary realisation kolibri_IPC_send(message->tid, KOBRA_MEMAREA_NAME, KOBRA_MEMAREA_NAME_LENGTH); default: // Here should be some error handler return; } } } thread_list_t *find_tid(group_list_t *group, int tid){ thread_list_t *thread_list = group->thread_list, *thread = thread_list; if (!thread_list) { return NULL; } do { if (thread->tid == tid) { return thread; } thread = thread->next; } while (thread != thread_list); return NULL; } void kobra_register(int tid){ add_to_group(main_group_list, tid); } void add_to_group(group_list_t *group, int tid){ thread_list_t *thread_list = group->thread_list, *thread_last; if (!thread_list) { thread_list = group->thread_list = new_thread_list(tid); thread_list->previos = thread_list->next = thread_list; } else if (thread_list == (thread_last = thread_list->previos)) { thread_last = thread_list->next = thread_list->previos = new_thread_list(tid); thread_last->next = thread_last->previos = thread_list; } else { thread_last->next = thread_list->previos = new_thread_list(tid); thread_last->next->next = thread_list; thread_last->next->previos = thread_last; } } void remove_from_group(group_list_t *group, thread_list_t *thread){ if (thread->next == thread) { remove_group(group); } else { thread->next->previos = thread->previos; thread->previos->next = thread->next; if (group->thread_list == thread) { group->thread_list = thread->next; } } memarea_free(thread); } group_list_t *find_group(char *name){ group_list_t *group_list = main_group_list, *group = group_list; if (group_list) { do { if (!strcmp(group->name, name)) { return group; } group = group->next; } while (group != group_list); } return NULL; } void send_group_message(group_list_t *group, int tid, char *message, int length){ thread_list_t *thread_list = group->thread_list, *thread = thread_list; char *msg = malloc(length+sizeof(int)); ((unsigned long *)msg)[0] = (unsigned long)tid; memcpy(msg+4, message, length); do { IPCSend(thread->tid, msg, length+sizeof(int)); // Here may be some errror handler thread = thread->next; } while (thread != thread_list); } void remove_group(group_list_t *group){ if (group == main_group_list) { return; } group->next->previos = group->previos; group->previos->next = group->next; memarea_free(group); } group_list_t *create_group(char *name){ group_list_t *group_list = main_group_list, *group_last; if (!group_list) { return main_group_list = new_group_list(name); } group_last = group_list->previos; if (group_list == group_last) { group_last = group_list->next = group_list->previos = new_group_list(name); group_last->next = group_last->previos = group_list; } else { group_last->next = group_list->previos = new_group_list(name); group_last->next->next = group_list; group_last->next->previos = group_last; group_last = group_last->next; } return group_last; } group_list_t *new_group_list(char *name){ group_list_t *list = memarea_alloc(sizeof(group_list_t)); if (list) { list->name = malloc(strlen(name)); strcpy(list->name, name); list->thread_list = NULL; } return list; } thread_list_t *new_thread_list(int tid){ thread_list_t *list = memarea_alloc(sizeof(thread_list_t)); if (list) { list->tid = tid; } return list; } asm(".align 16\n.globl end\nend:");