1) First commit of libIPC
2) Kobra (0.1.1) uses libIPC, compilation changed, files with non-kobra functions moved to framework git-svn-id: svn://kolibrios.org@1286 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
139
programs/develop/libraries/framework/trunk/libIPC/ipc.c
Normal file
139
programs/develop/libraries/framework/trunk/libIPC/ipc.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (C) Vasiliy Kosenko (vkos), 2009 *
|
||||
* This program 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. *
|
||||
* *
|
||||
* This program 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 this program. *
|
||||
* If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <ipc.h>
|
||||
#include <malloc.h>
|
||||
#include <kolibri.h>
|
||||
#include <defs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* High level IPC functions
|
||||
*/
|
||||
|
||||
IPCArea *ipc_area = NULL;
|
||||
|
||||
int IPCInit(void){
|
||||
ipc_area = malloc(IPC_BUFFER_SIZE);
|
||||
if (!ipc_area) {
|
||||
return IPC_NO_MEMORY;
|
||||
}
|
||||
return kolibri_IPC_init(ipc_area, IPC_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
int IPCSend(int tid, void *message, int length){
|
||||
int err_count = IPC_MAX_ERRORS;
|
||||
int err;
|
||||
|
||||
while (--err_count) {
|
||||
if (!(err = kolibri_IPC_send(tid, message, length)) || err == IPC_NO_AREA || err == IPC_NO_TID) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
bool IPCCheck(void){
|
||||
return IPCCheckWait(0);
|
||||
}
|
||||
|
||||
bool IPCCheckWait(int time){
|
||||
int result = false;
|
||||
int emask = kolibri_event_get_mask();
|
||||
|
||||
kolibri_event_set_mask(KOLIBRI_EVENT_IPC_MASK);
|
||||
|
||||
result = kolibri_event_wait(time);
|
||||
|
||||
kolibri_event_set_mask(emask);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Message *IPCGetNextMessage(void){
|
||||
return IPCWaitMessage(0);
|
||||
}
|
||||
|
||||
Message *IPCWaitMessage(int time){
|
||||
if (IPCCheckWait(time)){
|
||||
Message *msg_ret, *msg = kolibri_IPC_get_next_message();
|
||||
msg_ret = malloc(sizeof(Message)+msg->length);
|
||||
if (!msg_ret) {
|
||||
return NULL;
|
||||
}
|
||||
IPCLock();
|
||||
memcpy(msg_ret, msg, sizeof(Message)+msg->length);
|
||||
ipc_area->size -= sizeof(Message)+msg->length;
|
||||
memcpy(msg, msg+sizeof(Message)+msg->length, ipc_area->size);
|
||||
IPCUnlock();
|
||||
return msg_ret;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Kolibri IPC functions & data
|
||||
*/
|
||||
|
||||
kolibri_IPC_area_t *kolibri_ipc_area;
|
||||
|
||||
int kolibri_IPC_set_area(void *area, int size){
|
||||
int result;
|
||||
|
||||
asm("int $0x40":"=a"(result):"a"(60),"b"(1),"c"(area),"d"(size));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int kolibri_IPC_send(int tid, void *msg, int length){
|
||||
int result;
|
||||
|
||||
asm("movl %5, %%esi\nint $0x40":"=a"(result):"a"(60),"b"(2),"c"(tid),"d"(msg),"g"(length));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void kolibri_IPC_unlock(){
|
||||
kolibri_ipc_area->lock = 0;
|
||||
}
|
||||
|
||||
void kolibri_IPC_lock(){
|
||||
kolibri_ipc_area->lock = 1;
|
||||
}
|
||||
|
||||
int kolibri_IPC_init(void *area, int size){
|
||||
kolibri_ipc_area = (kolibri_IPC_area_t *)area;
|
||||
kolibri_ipc_area->size = 8;
|
||||
|
||||
return kolibri_IPC_set_area(area, size);
|
||||
}
|
||||
|
||||
kolibri_IPC_message_t *kolibri_IPC_get_next_message(){
|
||||
kolibri_IPC_lock();
|
||||
return (kolibri_IPC_message_t *)((char *)kolibri_ipc_area+sizeof(kolibri_IPC_area_t));
|
||||
}
|
||||
|
||||
void IPCLock(void){
|
||||
kolibri_IPC_lock();
|
||||
}
|
||||
|
||||
void IPCUnlock(void){
|
||||
kolibri_IPC_unlock();
|
||||
}
|
||||
|
||||
// void kolibri_IPC_clear_buff(){
|
||||
// kolibri_ipc_area->size = 8;
|
||||
// kolibri_IPC_unlock();
|
||||
// }
|
59
programs/develop/libraries/framework/trunk/libIPC/ipc.txt
Normal file
59
programs/develop/libraries/framework/trunk/libIPC/ipc.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
LibIPC -- библиотека межпотокового взаимодействия
|
||||
=================================================
|
||||
|
||||
|
||||
Интерфейс
|
||||
---------
|
||||
|
||||
**LibIPC** будет предоставлять следующие функции:
|
||||
|
||||
int **IPCInit**\(void);
|
||||
Инициализация IPC. При этом должна быть инициализирована куча для динамического
|
||||
выделения памяти под буфер. Возвращает 0 = **SUCCESS** в случае удачи, в противном
|
||||
случае код ошибки:
|
||||
|
||||
- **NO_MEMORY** (=1) -- невозможно получить память
|
||||
- **CANNOT_SET_MASK** (=2) -- невозможно установить маску событий
|
||||
- *n* + 2 -- системная функция завершилась с ошибкой *n*
|
||||
|
||||
int **IPCSend**\(int *tid*, void *\*message*, int *length*);
|
||||
Послать сообщение. Если произошла системная ошибка 2 или 3, будут произведены
|
||||
дополнительные попытки (не больше какой-то константы). В случае успеха
|
||||
возвращает 0, коды ошибок:
|
||||
|
||||
- **IPC_NO_AREA** (=1) -- поток не определил область IPC
|
||||
- **IPC_BUFFER_LOCKED** (=2) -- были ошибки 2 и 3, при последней попытке -- ошибка 2 (поток заблокировал буфер)
|
||||
- **IPC_OVERFLOW** (=3) -- то же, что и 2, только последняя ошибка 3 (переполнение буфера)
|
||||
- **IPC_NO_TID** (=4) -- единственная или последняя ошибка была 4, т.е. отсутствие потока с заданным TID
|
||||
|
||||
bool **IPCCheck**\(void);
|
||||
Проверить, не пришло ли новое сообщение.
|
||||
|
||||
Message \*\ **IPCGetNextMessage**\(void);
|
||||
Получить следующее сообщение. То же самое, что **IPCWaitMessage**\(0).
|
||||
|
||||
Message \*\ **IPCWaitMessage**\(int *time*);
|
||||
Ждать сообщения не больше time миллисекунд (-1 = ждать вечно). При этом
|
||||
сообщение удаляется из буфера и копируется в динамически выделяемую область
|
||||
памяти. Если сообщения нет (или произошла ошибка выделения памяти),
|
||||
возвращается **NULL**, если есть -- адрес на структуру Message::
|
||||
|
||||
typedef struct Message {
|
||||
int tid;
|
||||
int length;
|
||||
//void msg;
|
||||
} Message;
|
||||
|
||||
void **IPCLock**\(void);
|
||||
Функция ручной блокировки буфера (в большинстве случаев не нужна, т.к.
|
||||
библиотека сама блокирует буфер в нужных случаях).
|
||||
|
||||
void **IPCUnclock**\(void);
|
||||
Функция, обратная **IPCLock**\();
|
||||
|
||||
|
||||
Форма реализации
|
||||
----------------
|
||||
|
||||
- Язык: **C**
|
||||
- Формат: .o -- поддержка C, asm и т.д. Динамичность библиотеки в данном случае бессмысленна.
|
@@ -0,0 +1,5 @@
|
||||
ROOT=..
|
||||
|
||||
include ../config.mk
|
||||
|
||||
all: ipc.o
|
Reference in New Issue
Block a user